common.php 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  1. <?php
  2. // 公共助手函数
  3. use think\exception\HttpResponseException;
  4. use think\Response;
  5. use think\Session;
  6. if (!function_exists('__')) {
  7. /**
  8. * 获取语言变量值
  9. * @param string $name 语言变量名
  10. * @param array $vars 动态变量值
  11. * @param string $lang 语言
  12. * @return mixed
  13. */
  14. function __($name, $vars = [], $lang = '')
  15. {
  16. if (is_numeric($name) || !$name) {
  17. return $name;
  18. }
  19. if (!is_array($vars)) {
  20. $vars = func_get_args();
  21. array_shift($vars);
  22. $lang = '';
  23. }
  24. return \think\Lang::get($name, $vars, $lang);
  25. }
  26. }
  27. if (!function_exists('mask_email')) {
  28. /**
  29. * 邮箱脱敏:本地部分前三位 + *** + 域名中最后一个点及其后缀
  30. * 例:14906570@qq.com → 149***.com;yjf123@163.com → yjf***.com
  31. */
  32. function mask_email($email)
  33. {
  34. $email = trim((string)$email);
  35. if ($email === '') {
  36. return '';
  37. }
  38. $at = mb_strpos($email, '@', 0, 'UTF-8');
  39. if ($at === false) {
  40. if (mb_strlen($email, 'UTF-8') <= 3) {
  41. return $email;
  42. }
  43. $lastDot = mb_strrpos($email, '.', 0, 'UTF-8');
  44. if ($lastDot === false || $lastDot < 3) {
  45. return mb_substr($email, 0, 3, 'UTF-8') . '***';
  46. }
  47. return mb_substr($email, 0, 3, 'UTF-8') . '***' . mb_substr($email, $lastDot, null, 'UTF-8');
  48. }
  49. $local = mb_substr($email, 0, $at, 'UTF-8');
  50. $domain = mb_substr($email, $at + 1, null, 'UTF-8');
  51. if ($domain === '') {
  52. if (mb_strlen($local, 'UTF-8') <= 3) {
  53. return $local;
  54. }
  55. return mb_substr($local, 0, 3, 'UTF-8') . '***';
  56. }
  57. $first3 = mb_strlen($local, 'UTF-8') <= 3
  58. ? $local
  59. : mb_substr($local, 0, 3, 'UTF-8');
  60. $lastDot = mb_strrpos($domain, '.', 0, 'UTF-8');
  61. if ($lastDot === false) {
  62. return $first3 . '***@' . $domain;
  63. }
  64. return $first3 . '***' . mb_substr($domain, $lastDot, null, 'UTF-8');
  65. }
  66. }
  67. if (!function_exists('mask_phone')) {
  68. /**
  69. * 手机号脱敏:前三位 + 星号 + 后四位
  70. * 例:18981046362 → 189****6362
  71. */
  72. function mask_phone($phone)
  73. {
  74. $phone = preg_replace('/\s+/', '', trim((string)$phone));
  75. if ($phone === '') {
  76. return '';
  77. }
  78. $len = strlen($phone);
  79. if ($len <= 7) {
  80. if ($len <= 3) {
  81. return $phone;
  82. }
  83. return substr($phone, 0, 3) . str_repeat('*', $len - 3);
  84. }
  85. return substr($phone, 0, 3) . str_repeat('*', $len - 7) . substr($phone, -4);
  86. }
  87. }
  88. if (!function_exists('default_admin_avatar_url')) {
  89. /**
  90. * 后台管理员默认头像(站点品牌 Logo)
  91. */
  92. function default_admin_avatar_url(): string
  93. {
  94. $url = \think\Config::get('site.brand_logo');
  95. $url = trim((string)$url);
  96. return $url !== '' ? $url : 'https://a-7in6-com.oss-cn-hangzhou.aliyuncs.com/xinhua/img/logo1.png';
  97. }
  98. }
  99. if (!function_exists('is_default_admin_avatar')) {
  100. /**
  101. * 是否为系统默认头像(未上传自定义头像)
  102. */
  103. function is_default_admin_avatar($avatar): bool
  104. {
  105. $avatar = trim((string)$avatar);
  106. if ($avatar === '') {
  107. return true;
  108. }
  109. if ($avatar === default_admin_avatar_url()) {
  110. return true;
  111. }
  112. if (preg_match('#/assets/img/avatar\.png(?:\?.*)?$#i', $avatar)) {
  113. return true;
  114. }
  115. return in_array($avatar, ['/assets/img/avatar.png', 'assets/img/avatar.png'], true);
  116. }
  117. }
  118. if (!function_exists('resolve_admin_avatar')) {
  119. /**
  120. * 展示用管理员头像:未上传自定义头像时用默认 Logo
  121. */
  122. function resolve_admin_avatar($avatar): string
  123. {
  124. $avatar = trim((string)$avatar);
  125. return is_default_admin_avatar($avatar) ? default_admin_avatar_url() : $avatar;
  126. }
  127. }
  128. if (!function_exists('format_bytes')) {
  129. /**
  130. * 将字节转换为可读文本
  131. * @param int $size 大小
  132. * @param string $delimiter 分隔符
  133. * @param int $precision 小数位数
  134. * @return string
  135. */
  136. function format_bytes($size, $delimiter = '', $precision = 2)
  137. {
  138. $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
  139. for ($i = 0; $size >= 1024 && $i < 6; $i++) {
  140. $size /= 1024;
  141. }
  142. return round($size, $precision) . $delimiter . $units[$i];
  143. }
  144. }
  145. if (!function_exists('datetime')) {
  146. /**
  147. * 将时间戳转换为日期时间
  148. * @param int $time 时间戳
  149. * @param string $format 日期时间格式
  150. * @return string
  151. */
  152. function datetime($time, $format = 'Y-m-d H:i:s')
  153. {
  154. $time = is_numeric($time) ? $time : strtotime($time);
  155. return date($format, $time);
  156. }
  157. }
  158. if (!function_exists('human_date')) {
  159. /**
  160. * 获取语义化时间
  161. * @param int $time 时间
  162. * @param int $local 本地时间
  163. * @return string
  164. */
  165. function human_date($time, $local = null)
  166. {
  167. return \fast\Date::human($time, $local);
  168. }
  169. }
  170. if (!function_exists('cdnurl')) {
  171. /**
  172. * 获取上传资源的CDN的地址
  173. * @param string $url 资源相对地址
  174. * @param boolean $domain 是否显示域名 或者直接传入域名
  175. * @return string
  176. */
  177. function cdnurl($url, $domain = false)
  178. {
  179. $regex = "/^((?:[a-z]+:)?\/\/|data:image\/)(.*)/i";
  180. $cdnurl = \think\Config::get('upload.cdnurl');
  181. if (is_bool($domain) || stripos($cdnurl, '/') === 0) {
  182. $url = preg_match($regex, $url) || ($cdnurl && stripos($url, $cdnurl) === 0) ? $url : $cdnurl . $url;
  183. }
  184. if ($domain && !preg_match($regex, $url)) {
  185. $domain = is_bool($domain) ? request()->domain() : $domain;
  186. $url = $domain . $url;
  187. }
  188. return $url;
  189. }
  190. }
  191. if (!function_exists('is_really_writable')) {
  192. /**
  193. * 判断文件或文件夹是否可写
  194. * @param string $file 文件或目录
  195. * @return bool
  196. */
  197. function is_really_writable($file)
  198. {
  199. if (DIRECTORY_SEPARATOR === '/') {
  200. return is_writable($file);
  201. }
  202. if (is_dir($file)) {
  203. $file = rtrim($file, '/') . '/' . md5(mt_rand());
  204. if (($fp = @fopen($file, 'ab')) === false) {
  205. return false;
  206. }
  207. fclose($fp);
  208. @chmod($file, 0777);
  209. @unlink($file);
  210. return true;
  211. } elseif (!is_file($file) or ($fp = @fopen($file, 'ab')) === false) {
  212. return false;
  213. }
  214. fclose($fp);
  215. return true;
  216. }
  217. }
  218. if (!function_exists('rmdirs')) {
  219. /**
  220. * 删除文件夹
  221. * @param string $dirname 目录
  222. * @param bool $withself 是否删除自身
  223. * @return boolean
  224. */
  225. function rmdirs($dirname, $withself = true)
  226. {
  227. if (!is_dir($dirname)) {
  228. return false;
  229. }
  230. $files = new RecursiveIteratorIterator(
  231. new RecursiveDirectoryIterator($dirname, RecursiveDirectoryIterator::SKIP_DOTS),
  232. RecursiveIteratorIterator::CHILD_FIRST
  233. );
  234. foreach ($files as $fileinfo) {
  235. $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink');
  236. $todo($fileinfo->getRealPath());
  237. }
  238. if ($withself) {
  239. @rmdir($dirname);
  240. }
  241. return true;
  242. }
  243. }
  244. if (!function_exists('copydirs')) {
  245. /**
  246. * 复制文件夹
  247. * @param string $source 源文件夹
  248. * @param string $dest 目标文件夹
  249. */
  250. function copydirs($source, $dest)
  251. {
  252. if (!is_dir($dest)) {
  253. mkdir($dest, 0755, true);
  254. }
  255. foreach (
  256. $iterator = new RecursiveIteratorIterator(
  257. new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS),
  258. RecursiveIteratorIterator::SELF_FIRST
  259. ) as $item
  260. ) {
  261. if ($item->isDir()) {
  262. $sontDir = $dest . DS . $iterator->getSubPathName();
  263. if (!is_dir($sontDir)) {
  264. mkdir($sontDir, 0755, true);
  265. }
  266. } else {
  267. copy($item, $dest . DS . $iterator->getSubPathName());
  268. }
  269. }
  270. }
  271. }
  272. if (!function_exists('mb_ucfirst')) {
  273. function mb_ucfirst($string)
  274. {
  275. return mb_strtoupper(mb_substr($string, 0, 1)) . mb_strtolower(mb_substr($string, 1));
  276. }
  277. }
  278. if (!function_exists('addtion')) {
  279. /**
  280. * 附加关联字段数据
  281. * @param array $items 数据列表
  282. * @param mixed $fields 渲染的来源字段
  283. * @return array
  284. */
  285. function addtion($items, $fields)
  286. {
  287. if (!$items || !$fields) {
  288. return $items;
  289. }
  290. $fieldsArr = [];
  291. if (!is_array($fields)) {
  292. $arr = explode(',', $fields);
  293. foreach ($arr as $k => $v) {
  294. $fieldsArr[$v] = ['field' => $v];
  295. }
  296. } else {
  297. foreach ($fields as $k => $v) {
  298. if (is_array($v)) {
  299. $v['field'] = $v['field'] ?? $k;
  300. } else {
  301. $v = ['field' => $v];
  302. }
  303. $fieldsArr[$v['field']] = $v;
  304. }
  305. }
  306. foreach ($fieldsArr as $k => &$v) {
  307. $v = is_array($v) ? $v : ['field' => $v];
  308. $v['display'] = $v['display'] ?? str_replace(['_ids', '_id'], ['_names', '_name'], $v['field']);
  309. $v['primary'] = $v['primary'] ?? '';
  310. $v['column'] = $v['column'] ?? 'name';
  311. $v['model'] = $v['model'] ?? '';
  312. $v['table'] = $v['table'] ?? '';
  313. $v['name'] = $v['name'] ?? str_replace(['_ids', '_id'], '', $v['field']);
  314. }
  315. unset($v);
  316. $ids = [];
  317. $fields = array_keys($fieldsArr);
  318. foreach ($items as $k => $v) {
  319. foreach ($fields as $m => $n) {
  320. if (isset($v[$n])) {
  321. $ids[$n] = array_merge(isset($ids[$n]) && is_array($ids[$n]) ? $ids[$n] : [], explode(',', $v[$n]));
  322. }
  323. }
  324. }
  325. $result = [];
  326. foreach ($fieldsArr as $k => $v) {
  327. if ($v['model']) {
  328. $model = new $v['model'];
  329. } else {
  330. $model = $v['name'] ? \think\Db::name($v['name']) : \think\Db::table($v['table']);
  331. }
  332. $primary = $v['primary'] ? $v['primary'] : $model->getPk();
  333. $result[$v['field']] = isset($ids[$v['field']]) ? $model->where($primary, 'in', $ids[$v['field']])->column($v['column'], $primary) : [];
  334. }
  335. foreach ($items as $k => &$v) {
  336. foreach ($fields as $m => $n) {
  337. if (isset($v[$n])) {
  338. $curr = array_flip(explode(',', $v[$n]));
  339. $linedata = array_intersect_key($result[$n], $curr);
  340. $v[$fieldsArr[$n]['display']] = $fieldsArr[$n]['column'] == '*' ? $linedata : implode(',', $linedata);
  341. }
  342. }
  343. }
  344. return $items;
  345. }
  346. }
  347. if (!function_exists('var_export_short')) {
  348. /**
  349. * 使用短标签打印或返回数组结构
  350. * @param mixed $data
  351. * @param boolean $return 是否返回数据
  352. * @return string
  353. */
  354. function var_export_short($data, $return = true)
  355. {
  356. return var_export($data, $return);
  357. $replaced = [];
  358. $count = 0;
  359. //判断是否是对象
  360. if (is_resource($data) || is_object($data)) {
  361. return var_export($data, $return);
  362. }
  363. //判断是否有特殊的键名
  364. $specialKey = false;
  365. array_walk_recursive($data, function (&$value, &$key) use (&$specialKey) {
  366. if (is_string($key) && (stripos($key, "\n") !== false || stripos($key, "array (") !== false)) {
  367. $specialKey = true;
  368. }
  369. });
  370. if ($specialKey) {
  371. return var_export($data, $return);
  372. }
  373. array_walk_recursive($data, function (&$value, &$key) use (&$replaced, &$count, &$stringcheck) {
  374. if (is_object($value) || is_resource($value)) {
  375. $replaced[$count] = var_export($value, true);
  376. $value = "##<{$count}>##";
  377. } else {
  378. if (is_string($value) && (stripos($value, "\n") !== false || stripos($value, "array (") !== false)) {
  379. $index = array_search($value, $replaced);
  380. if ($index === false) {
  381. $replaced[$count] = var_export($value, true);
  382. $value = "##<{$count}>##";
  383. } else {
  384. $value = "##<{$index}>##";
  385. }
  386. }
  387. }
  388. $count++;
  389. });
  390. $dump = var_export($data, true);
  391. $dump = preg_replace('#(?:\A|\n)([ ]*)array \(#i', '[', $dump); // Starts
  392. $dump = preg_replace('#\n([ ]*)\),#', "\n$1],", $dump); // Ends
  393. $dump = preg_replace('#=> \[\n\s+\],\n#', "=> [],\n", $dump); // Empties
  394. $dump = preg_replace('#\)$#', "]", $dump); //End
  395. if ($replaced) {
  396. $dump = preg_replace_callback("/'##<(\d+)>##'/", function ($matches) use ($replaced) {
  397. return $replaced[$matches[1]] ?? "''";
  398. }, $dump);
  399. }
  400. if ($return === true) {
  401. return $dump;
  402. } else {
  403. echo $dump;
  404. }
  405. }
  406. }
  407. if (!function_exists('letter_avatar')) {
  408. /**
  409. * 首字母头像
  410. * @param $text
  411. * @return string
  412. */
  413. function letter_avatar($text)
  414. {
  415. $total = unpack('L', hash('adler32', $text, true))[1];
  416. $hue = $total % 360;
  417. list($r, $g, $b) = hsv2rgb($hue / 360, 0.3, 0.9);
  418. $bg = "rgb({$r},{$g},{$b})";
  419. $color = "#ffffff";
  420. $first = mb_strtoupper(mb_substr($text, 0, 1));
  421. $src = base64_encode('<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="100" width="100"><rect fill="' . $bg . '" x="0" y="0" width="100" height="100"></rect><text x="50" y="50" font-size="50" text-copy="fast" fill="' . $color . '" text-anchor="middle" text-rights="admin" dominant-baseline="central">' . $first . '</text></svg>');
  422. $value = 'data:image/svg+xml;base64,' . $src;
  423. return $value;
  424. }
  425. }
  426. if (!function_exists('hsv2rgb')) {
  427. function hsv2rgb($h, $s, $v)
  428. {
  429. $r = $g = $b = 0;
  430. $i = floor($h * 6);
  431. $f = $h * 6 - $i;
  432. $p = $v * (1 - $s);
  433. $q = $v * (1 - $f * $s);
  434. $t = $v * (1 - (1 - $f) * $s);
  435. switch ($i % 6) {
  436. case 0:
  437. $r = $v;
  438. $g = $t;
  439. $b = $p;
  440. break;
  441. case 1:
  442. $r = $q;
  443. $g = $v;
  444. $b = $p;
  445. break;
  446. case 2:
  447. $r = $p;
  448. $g = $v;
  449. $b = $t;
  450. break;
  451. case 3:
  452. $r = $p;
  453. $g = $q;
  454. $b = $v;
  455. break;
  456. case 4:
  457. $r = $t;
  458. $g = $p;
  459. $b = $v;
  460. break;
  461. case 5:
  462. $r = $v;
  463. $g = $p;
  464. $b = $q;
  465. break;
  466. }
  467. return [
  468. floor($r * 255),
  469. floor($g * 255),
  470. floor($b * 255)
  471. ];
  472. }
  473. }
  474. if (!function_exists('check_nav_active')) {
  475. /**
  476. * 检测会员中心导航是否高亮
  477. */
  478. function check_nav_active($url, $classname = 'active')
  479. {
  480. $auth = \app\common\library\Auth::instance();
  481. $requestUrl = $auth->getRequestUri();
  482. $url = ltrim($url, '/');
  483. return $requestUrl === str_replace(".", "/", $url) ? $classname : '';
  484. }
  485. }
  486. if (!function_exists('check_cors_request')) {
  487. /**
  488. * 跨域检测
  489. */
  490. function check_cors_request()
  491. {
  492. if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN'] && config('fastadmin.cors_request_domain')) {
  493. $info = parse_url($_SERVER['HTTP_ORIGIN']);
  494. $domainArr = explode(',', config('fastadmin.cors_request_domain'));
  495. $domainArr[] = request()->host(true);
  496. if (in_array("*", $domainArr) || in_array($_SERVER['HTTP_ORIGIN'], $domainArr) || (isset($info['host']) && in_array($info['host'], $domainArr))) {
  497. header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
  498. } else {
  499. $response = Response::create('跨域检测无效', 'html', 403);
  500. throw new HttpResponseException($response);
  501. }
  502. header('Access-Control-Allow-Credentials: true');
  503. header('Access-Control-Max-Age: 86400');
  504. if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
  505. if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
  506. header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
  507. }
  508. if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
  509. header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
  510. }
  511. $response = Response::create('', 'html');
  512. throw new HttpResponseException($response);
  513. }
  514. }
  515. }
  516. }
  517. if (!function_exists('xss_clean')) {
  518. /**
  519. * 清理XSS
  520. */
  521. function xss_clean($content, $is_image = false)
  522. {
  523. return \app\common\library\Security::instance()->xss_clean($content, $is_image);
  524. }
  525. }
  526. if (!function_exists('url_clean')) {
  527. /**
  528. * 清理URL
  529. */
  530. function url_clean($url)
  531. {
  532. if (!check_url_allowed($url)) {
  533. return '';
  534. }
  535. return xss_clean($url);
  536. }
  537. }
  538. if (!function_exists('check_ip_allowed')) {
  539. /**
  540. * 检测IP是否允许
  541. * @param string $ip IP地址
  542. */
  543. function check_ip_allowed($ip = null)
  544. {
  545. $ip = is_null($ip) ? request()->ip() : $ip;
  546. $forbiddenipArr = config('site.forbiddenip');
  547. $forbiddenipArr = !$forbiddenipArr ? [] : $forbiddenipArr;
  548. $forbiddenipArr = is_array($forbiddenipArr) ? $forbiddenipArr : array_filter(explode("\n", str_replace("\r\n", "\n", $forbiddenipArr)));
  549. if ($forbiddenipArr && \Symfony\Component\HttpFoundation\IpUtils::checkIp($ip, $forbiddenipArr)) {
  550. $response = Response::create('请求无权访问', 'html', 403);
  551. throw new HttpResponseException($response);
  552. }
  553. }
  554. }
  555. if (!function_exists('check_url_allowed')) {
  556. /**
  557. * 检测URL是否允许
  558. * @param string $url URL
  559. * @return bool
  560. */
  561. function check_url_allowed($url = '')
  562. {
  563. //允许的主机列表
  564. $allowedHostArr = [
  565. strtolower(request()->host())
  566. ];
  567. if (empty($url)) {
  568. return true;
  569. }
  570. //如果是站内相对链接则允许
  571. if (preg_match("/^[\/a-z][a-z0-9][a-z0-9\.\/]+((\?|#).*)?\$/i", $url) && substr($url, 0, 2) !== '//') {
  572. return true;
  573. }
  574. //如果是站外链接则需要判断HOST是否允许
  575. if (preg_match("/((http[s]?:\/\/)+(?>[a-z\-0-9]{2,}\.){1,}[a-z]{2,8})(?:\s|\/)/i", $url)) {
  576. $chkHost = parse_url(strtolower($url), PHP_URL_HOST);
  577. if ($chkHost && in_array($chkHost, $allowedHostArr)) {
  578. return true;
  579. }
  580. }
  581. return false;
  582. }
  583. }
  584. if (!function_exists('build_suffix_image')) {
  585. /**
  586. * 生成文件后缀图片
  587. * @param string $suffix 后缀
  588. * @param null $background
  589. * @return string
  590. */
  591. function build_suffix_image($suffix, $background = null)
  592. {
  593. $suffix = mb_substr(strtoupper($suffix), 0, 4);
  594. $total = unpack('L', hash('adler32', $suffix, true))[1];
  595. $hue = $total % 360;
  596. list($r, $g, $b) = hsv2rgb($hue / 360, 0.3, 0.9);
  597. $background = $background ? $background : "rgb({$r},{$g},{$b})";
  598. $icon = <<<EOT
  599. <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
  600. <path style="fill:#E2E5E7;" d="M128,0c-17.6,0-32,14.4-32,32v448c0,17.6,14.4,32,32,32h320c17.6,0,32-14.4,32-32V128L352,0H128z"/>
  601. <path style="fill:#B0B7BD;" d="M384,128h96L352,0v96C352,113.6,366.4,128,384,128z"/>
  602. <polygon style="fill:#CAD1D8;" points="480,224 384,128 480,128 "/>
  603. <path style="fill:{$background};" d="M416,416c0,8.8-7.2,16-16,16H48c-8.8,0-16-7.2-16-16V256c0-8.8,7.2-16,16-16h352c8.8,0,16,7.2,16,16 V416z"/>
  604. <path style="fill:#CAD1D8;" d="M400,432H96v16h304c8.8,0,16-7.2,16-16v-16C416,424.8,408.8,432,400,432z"/>
  605. <g><text><tspan x="220" y="380" font-size="124" font-family="Verdana, Helvetica, Arial, sans-serif" fill="white" text-anchor="middle">{$suffix}</tspan></text></g>
  606. </svg>
  607. EOT;
  608. return $icon;
  609. }
  610. }
  611. //获取Session缓存数据
  612. function getSessionData($key,$expire_time){
  613. $seseeion_key = md5($key);
  614. $seseeion_key_time = $seseeion_key.'_ctime';
  615. $seseeion_key_data = $seseeion_key.'_data';
  616. $seseeion_time = Session::get($seseeion_key_time);
  617. $seseeion_data = Session::get($seseeion_key_data);
  618. if($seseeion_time && $seseeion_data
  619. && ( time() - $seseeion_time <= $expire_time) ){
  620. //返回缓存数据
  621. $res = json_decode($seseeion_data,true);
  622. return $res;
  623. }
  624. return [];
  625. }
  626. //设置Session缓存数据
  627. function setSessionData($key,$data){
  628. $seseeion_key = md5($key);
  629. $seseeion_key_time = $seseeion_key.'_ctime';
  630. $seseeion_key_data = $seseeion_key.'_data';
  631. Session::set($seseeion_key_time,time());
  632. if(is_array($data)){
  633. $data = json_encode($data,320);
  634. }
  635. Session::set($seseeion_key_data,$data);
  636. return $data;
  637. }
  638. //=================大屏定义算法公式=======================================
  639. //只查看公斤单位数据
  640. function gongjin($info)
  641. {
  642. if ($info['cUnit'] == '公斤') {
  643. return floatval($info['nAmount']);
  644. } else {
  645. return 0;
  646. }
  647. }
  648. //只查看令单位数据)
  649. function ling($info)
  650. {
  651. if($info['cUnit'] == '令' && floatval($info['nhss']) > 0){
  652. return round($info['nAmount']/$info['nhss'],3);
  653. }else{
  654. return 0;
  655. }
  656. }
  657. //个别统一转换为(吨)单位
  658. function todun($info)
  659. {
  660. $dun = 0;
  661. if($info['cUnit'] == '令' && floatval($info['nhss']) > 0){
  662. $dun = round($info['nAmount']/$info['nhss'],3);
  663. }
  664. else if($info['cUnit'] == '张' && floatval($info['nhss']) > 0){
  665. $dun = round($info['nAmount']/500/$info['nhss'],3);
  666. }
  667. else if($info['cUnit'] == '公斤' && floatval($info['nhss']) > 0){
  668. $dun = round(floatval($info['nAmount'])/1000,3) ;
  669. }else if($info['cUnit'] == '米'){
  670. $dun = 0;
  671. }else if($info['cUnit'] == '张'){
  672. $dun = 0;
  673. }
  674. return $dun;
  675. }
  676. //个别统一转换为(公斤)单位
  677. function togongjin($info)
  678. {
  679. if($info['cUnit'] == '令' && floatval($info['nhss']) > 0){
  680. return round($info['nAmount']/$info['nhss'],3);
  681. }
  682. else if($info['cUnit'] == '张' && floatval($info['nhss']) > 0){
  683. return round($info['nAmount']/500/$info['nhss'],3);
  684. }
  685. else if($info['cUnit'] == '公斤'){
  686. return floatval($info['nAmount']);
  687. }
  688. return 0;
  689. }
  690. //获取转换为 单位万
  691. function gettowan($num){
  692. return intval($num/10000);
  693. }
  694. //分类信息——如有新增分类可添加 getCateName方法也要加
  695. function getcateinfo(){
  696. return [
  697. '有光双面铜版纸',
  698. '本白双胶纸',
  699. '特种纸',
  700. '彩画纸',
  701. '轻涂纸',
  702. '亚光双面铜版纸',
  703. '轻型纸',
  704. '白卡纸',
  705. '全灰板',
  706. '纯质纸',
  707. '高白双胶纸',
  708. '纯雅纸'
  709. ];
  710. }
  711. //各类纸张归类
  712. function getCateName($name){
  713. if(strpos($name,'有光双面铜版纸') !== false){
  714. return '有光双面铜版纸';
  715. }
  716. else if(strpos($name,'本白双胶纸') !== false){
  717. return '本白双胶纸';
  718. }
  719. else if(strpos($name,'特种纸') !== false){
  720. return '特种纸';
  721. }
  722. else if(strpos($name,'彩画纸') !== false){
  723. return '彩画纸';
  724. }
  725. else if(strpos($name,'轻涂纸') !== false){
  726. return '轻涂纸';
  727. }
  728. else if(strpos($name,'亚光双面铜版纸') !== false){
  729. return '亚光双面铜版纸';
  730. }
  731. else if(strpos($name,'轻型纸') !== false){
  732. return '轻型纸';
  733. }
  734. else if(strpos($name,'白卡纸') !== false){
  735. return '白卡纸';
  736. }
  737. else if(strpos($name,'高白双胶纸') !== false){
  738. return '高白双胶纸';
  739. }
  740. else if(strpos($name,'纯质纸') !== false){
  741. return '纯质纸';
  742. }
  743. else if(strpos($name,'全灰板') !== false){
  744. return '全灰板';
  745. }
  746. else if(strpos($name,'纯雅纸') !== false){
  747. return '纯雅纸';
  748. }
  749. return '未归类';
  750. }
  751. //判断名称分类
  752. function pdcateinfobyczgmc($czgmc){
  753. if(!$czgmc || empty($czgmc)){
  754. return '';
  755. }
  756. //getcateinfo自定义函数查询显示的固定分类
  757. $cateinfo = getcateinfo();
  758. if(in_array($czgmc,$cateinfo)){
  759. return $czgmc;
  760. }
  761. //
  762. foreach($cateinfo as $value){
  763. if(strpos($czgmc,$value) !== false){
  764. return $value;
  765. }
  766. }
  767. return '';
  768. }
  769. //补分类信息
  770. function bucateinfo($info=[])
  771. {
  772. $arr = getcateinfo();
  773. $tmp = [];
  774. foreach($arr as $value){
  775. if(!isset($info[$value]) ){
  776. $tmp[$value] = 0;
  777. }else{
  778. $tmp[$value] = $info[$value];
  779. }
  780. }
  781. return $tmp;
  782. }
  783. //获取今年年份信息
  784. function getYearInfo()
  785. {
  786. $y = [];
  787. $year= date('Y');
  788. for($i=1;$i<=12;$i++)
  789. {
  790. if($i < 10){
  791. $y[] = $year.'0'.$i;
  792. }
  793. else{
  794. $y[] = $year.$i;
  795. }
  796. }
  797. return $y;
  798. }
  799. //获取今年年月份
  800. function gettimeinfo($type=0){
  801. $start_time = date('Y-01-01').' 00:00:00';
  802. if($type == 1){
  803. return date('Y-m-d',strtotime($start_time .' + 1 year -1 day')) .' 23:59:59';
  804. }
  805. return $start_time;
  806. }
  807. //获取去年月份
  808. function getLastYear($type = 0) {
  809. $start_time = date('Y-01-01', strtotime('-1 year')) . ' 00:00:00';
  810. if ($type == 1) {
  811. return date('Y-m-d', strtotime($start_time . ' + 1 year -1 day')) . ' 23:59:59';
  812. }
  813. return $start_time;
  814. }
  815. //获取前年月份
  816. function getPreviousYear($type = 0) {
  817. $start_time = date('Y-01-01', strtotime('-2 years')) . ' 00:00:00';
  818. if ($type == 1) {
  819. return date('Y-m-d', strtotime($start_time . ' + 1 year -1 day')) . ' 23:59:59';
  820. }
  821. return $start_time;
  822. }
  823. //获取前年月份
  824. function getPreviousQYear($type = 0) {
  825. $start_time = date('Y-01-01', strtotime('-3 years')) . ' 00:00:00';
  826. if ($type == 1) {
  827. return date('Y-m-d', strtotime($start_time . ' + 1 year -1 day')) . ' 23:59:59';
  828. }
  829. return $start_time;
  830. }
  831. //规格字段处理
  832. function change($info){
  833. $infosize = $info['size'];
  834. if(!$infosize || empty($infosize)){
  835. return 0;
  836. }
  837. $infosize2 = explode('*',$info['size']);
  838. if(count($infosize2) >= 3){
  839. return 0;
  840. }
  841. $flag = false;
  842. foreach ($infosize2 as $size){
  843. if(!is_numeric($size)){
  844. $flag = true;break;
  845. }
  846. }
  847. if($flag){
  848. return 0;
  849. }
  850. $sizer = 1;
  851. foreach ($infosize2 as $size){
  852. $sizer = $sizer * $size;
  853. }
  854. return $sizer;
  855. }
  856. //保留3位数
  857. function toround($num){
  858. return sprintf("%.3f", $num);
  859. // return round($num,3);
  860. }
  861. //保留2位数
  862. function two_toround($num){
  863. return sprintf("%.2f", $num);
  864. // return round($num,3);
  865. }
  866. //采购平台数据库————采购量重量转换单位(吨)
  867. function cgl_weight($info){
  868. $infosize = floatval($info['size']);
  869. if(!$infosize){return 0;}
  870. $info['unit']= trim($info['unit']);
  871. $dun = 0;
  872. if($info['unit'] == '令' ){
  873. $dun = $info['number'] * 500 * $info['weight'] * pow(10, -12);
  874. }
  875. else if($info['unit'] == '张'){
  876. $dun = $info['number'] * $info['weight'] * pow(10, -12);
  877. }else if($info['unit'] == '米'){
  878. $dun = 0;
  879. }
  880. if($dun >= 0){
  881. $infosize = explode('*',$info['size']);
  882. foreach ($infosize as $size){
  883. $dun = $dun * floatval($size);
  884. }
  885. }
  886. if($info['unit'] == '吨'){
  887. $dun = $info['dunwei'];
  888. }
  889. return $dun;
  890. }
  891. //采购平台数据库————采购量重量转换单位(均价)
  892. function cgl_price($info){
  893. $infosize = floatval($info['size']);
  894. if(!$infosize){return 0;}
  895. $info['unit']= trim($info['unit']);
  896. $dun = 0;
  897. if($info['unit'] == '令' ){
  898. $dun = $info['number'] / 500 / $info['weight'];
  899. }
  900. else if($info['unit'] == '张' ){
  901. $dun = $info['number'] / $info['weight'] ;
  902. }else if($info['unit'] == '米'){
  903. $dun = 0;
  904. }
  905. if($dun >= 0){
  906. $infosize = explode('*',$info['size']);
  907. foreach ($infosize as $size){
  908. $dun = $dun / floatval($size);
  909. }
  910. }
  911. if($info['unit'] == '吨'){
  912. $dun = $info['price'];
  913. }
  914. $dun = $dun * pow(10, 12);
  915. return $dun;
  916. }
  917. //令 = 数量/吨折令
  918. //张 = 数量/吨折令/500
  919. //公斤 =数量/1000
  920. //米=0
  921. //吨折令 = 0 单位为:令/ 20、张/ 1.5 、
  922. //转换单位吨
  923. function erp_price($info){
  924. $info['unit']= trim($info['unit']);
  925. $dun = 0;
  926. if($info['unit'] == '令' ){
  927. if($info['nhss'] == 0){
  928. $dun = $info['number'] / 20;
  929. }else{
  930. $dun = $info['number'] / $info['nhss'];
  931. }
  932. }else if($info['unit'] == '张'){
  933. if($info['nhss'] == 0){
  934. $dun = $info['number'] / 1.5 / 500;
  935. }else{
  936. $dun = $info['number'] / $info['nhss'] / 500;
  937. }
  938. }else if($info['unit'] == '公斤'){
  939. $dun = $info['number'] / 1000;
  940. }else if($info['unit'] == '米'){
  941. $dun = 0;
  942. }
  943. return $dun;
  944. }
  945. //连接 Redis
  946. function redis(){
  947. $redis = new \Redis();
  948. // $redis->connect($this->redis_config['host'], $this->redis_config['port'], $this->redis_config['timeout']);
  949. $redis->connect('127.0.0.1','6379',16400,'');
  950. return $redis;
  951. }