// +---------------------------------------------------------------------- declare (strict_types=1); /** * 应用公共函数库文件 */ use think\Response; use think\facade\Env; use think\facade\Log; use think\facade\Config; use think\facade\Request; use cores\exception\BaseException; use cores\exception\DebugException; use think\exception\HttpResponseException; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Style\Alignment; use think\facade\Db; /** * 打印调试函数 html * @param $content * @param bool $export */ function pre($content, bool $export = false) { $output = $export ? var_export($content, true) : print_r($content, true); echo "
{$output}
"; app_end(); } /** * 打印调试函数 json * @param $content * @param bool $export * @throws DebugException */ function pree($content, bool $export = false) { $output = $export ? var_export($content, true) : $content; throw new DebugException([], $output); } /** * 打印调试函数 输出在终端 * 只有debug模式下输出 * @param $content * @return void */ function tre($content) { // if (is_debug()) { $output = print_r($content, true); echo "$output\n"; // } } /** * 输出错误信息 * @param string $message 报错信息 * @param int|null $status 状态码,默认为配置文件status.error * @param array $data 附加数据 * @throws BaseException */ function throwError(string $message, ?int $status = null, array $data = []) { is_null($status) && $status = config('status.error'); throw new BaseException(['status' => $status, 'message' => $message, 'data' => $data]); } /** * 下划线转驼峰 * @param string $uncamelized_words * @param string $separator * @return string */ function camelize(string $uncamelized_words, string $separator = '_'): string { $uncamelized_words = $separator . str_replace($separator, " ", strtolower($uncamelized_words)); return ltrim(str_replace(" ", "", ucwords($uncamelized_words)), $separator); } /** * 驼峰转下划线 * @param string $camelCaps * @param string $separator * @return string */ function uncamelize(string $camelCaps, string $separator = '_'): string { return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps)); } /** * 生成密码hash值 * @param string $password * @return string */ function encryption_hash(string $password): string { return password_hash($password, PASSWORD_DEFAULT); } /** * 获取当前域名及根路径 * @return string */ function base_url(): string { static $baseUrl = ''; if (empty($baseUrl)) { $request = Request::instance(); // url协议,设置强制https或自动获取 $scheme = Config::get('route')['url_force_https'] ? 'https' : $request->scheme(); // url子目录 $rootUrl = root_url(); // 拼接完整url $baseUrl = "{$scheme}://" . $request->host() . $rootUrl; } return $baseUrl; } /** * 获取当前url的子目录路径 * @return string */ function root_url(): string { static $rootUrl = ''; if (empty($rootUrl)) { $request = Request::instance(); $subUrl = str_replace('\\', '/', dirname($request->baseFile())); $rootUrl = $subUrl . ($subUrl === '/' ? '' : '/'); } return $rootUrl; } /** * 获取当前uploads目录访问地址 * @return string */ function uploads_url(): string { return base_url() . 'uploads/'; } /** * 获取当前temp目录访问地址 * @return string */ function temp_url(): string { return base_url() . 'temp/'; } /** * 获取当前的应用名称 * @return mixed */ function app_name() { return app('http')->getName(); } /** * 获取web根目录 * @return string */ function web_path(): string { static $webPath = ''; if (empty($webPath)) { $request = Request::instance(); $webPath = dirname($request->server('SCRIPT_FILENAME')) . DIRECTORY_SEPARATOR; } return $webPath; } /** * 获取data目录路径 * @return string */ function data_path(): string { return config('filesystem.disks.data.root') . DIRECTORY_SEPARATOR; } /** * 获取runtime根目录路径 * @return string */ function runtime_root_path(): string { // return dirname(runtime_path()) . DIRECTORY_SEPARATOR; return root_path() . 'runtime' . DIRECTORY_SEPARATOR; } /** * 写入日志 (使用tp自带驱动记录到runtime目录中) * @param mixed $value * @param string $type */ function log_record($value, string $type = 'info') { $content = is_string($value) ? $value : print_r($value, true); Log::record($content, $type); } /** * 多维数组合并 * @param $array1 * @param $array2 * @return array */ function array_merge_multiple($array1, $array2): array { $merge = $array1 + $array2; $data = []; foreach ($merge as $key => $val) { if ( isset($array1[$key]) && is_array($array1[$key]) && isset($array2[$key]) && is_array($array2[$key]) ) { $data[$key] = is_assoc($array1[$key]) ? array_merge_multiple($array1[$key], $array2[$key]) : $array2[$key]; } else { $data[$key] = $array2[$key] ?? $array1[$key]; } } return $data; } /** * 判断是否为自定义索引数组 * @param array $array * @return bool */ function is_assoc(array $array): bool { if (empty($array)) return false; return array_keys($array) !== range(0, count($array) - 1); } /** * 二维数组排序 * @param $arr * @param $keys * @param bool $desc * @return array */ function array_sort($arr, $keys, bool $desc): array { $key_value = $new_array = array(); foreach ($arr as $k => $v) { $key_value[$k] = $v[$keys]; } if ($desc) { arsort($key_value); } else { asort($key_value); } reset($key_value); foreach ($key_value as $k => $v) { $new_array[$k] = $arr[$k]; } return $new_array; } /** * 隐藏敏感字符 * @param $value * @return string */ function substr_cut($value): string { $strlen = mb_strlen($value, 'utf-8'); if ($strlen <= 1) return $value; $firstStr = mb_substr($value, 0, 1, 'utf-8'); $lastStr = mb_substr($value, -1, 1, 'utf-8'); return $strlen == 2 ? $firstStr . str_repeat('*', $strlen - 1) : $firstStr . str_repeat("*", $strlen - 2) . $lastStr; } /** * 获取当前系统版本号 * @return string * @throws BaseException */ function get_version(): string { return \cores\library\Version::getVersion(); } /** * 获取全局唯一标识符 * @param bool $trim * @return string */ function get_guid_v4(bool $trim = true): string { // Windows if (function_exists('com_create_guid') === true) { $charid = com_create_guid(); return $trim ? trim($charid, '{}') : $charid; } // OSX/Linux if (function_exists('openssl_random_pseudo_bytes') === true) { $data = openssl_random_pseudo_bytes(16); $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100 $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10 return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); } // Fallback (PHP 4.2+) mt_srand(intval((double)microtime() * 10000)); $charid = strtolower(md5(uniqid((string)rand(), true))); $hyphen = chr(45); // "-" $lbrace = $trim ? "" : chr(123); // "{" $rbrace = $trim ? "" : chr(125); // "}" return $lbrace . substr($charid, 0, 8) . $hyphen . substr($charid, 8, 4) . $hyphen . substr($charid, 12, 4) . $hyphen . substr($charid, 16, 4) . $hyphen . substr($charid, 20, 12) . $rbrace; } /** * 时间戳转换日期 * @param int|string $timeStamp 时间戳 * @param bool $withTime 是否关联时间 * @return false|string */ function format_time($timeStamp, bool $withTime = true) { $format = 'Y-m-d'; $withTime && $format .= ' H:i:s'; return $timeStamp ? date($format, $timeStamp) : ''; } /** * 左侧填充0 * @param string $value * @param int $padLength * @return string */ function pad_left(string $value, int $padLength = 2): string { return str_pad($value, $padLength, '0', STR_PAD_LEFT); } /** * 重写trim方法 (解决int类型过滤后后变为string类型) * @param $str * @return string|void */ function my_trim($str) { return is_string($str) ? trim($str) : $str; } /** * 重写htmlspecialchars方法 (解决int类型过滤后后变为string类型) * @param $string * @return string|void */ function my_htmlspecialchars($string) { return is_string($string) ? htmlspecialchars($string, ENT_COMPAT) : $string; } /** * 过滤emoji表情 * @param $text * @return null|string|string[] */ function filter_emoji($text) { if (!is_string($text)) { return $text; } // 此处的preg_replace用于过滤emoji表情 // 如需支持emoji表情, 需将mysql的编码改为utf8mb4 return preg_replace('/[\xf0-\xf7].{3}/', '', $text); } /** * 根据指定长度截取字符串 * @param $str * @param int $length * @return bool|string */ function str_substr($str, int $length = 30) { if (strlen($str) > $length) { $str = mb_substr($str, 0, $length); } return $str; } /** * 结束执行 */ function app_end() { if (\request()->isCli()) { exit(PHP_EOL); } throw new HttpResponseException(Response::create()); } /** * 当前是否为调试模式 * @return bool */ function is_debug(): bool { return (bool)Env::instance()->get('APP_DEBUG'); } /** * 文本左斜杠转换为右斜杠 * @param string $string * @return string */ function convert_left_slash(string $string): string { return str_replace('\\', '/', $string); } /** * 隐藏手机号中间四位 13012345678 -> 130****5678 * @param string $mobile 手机号 * @return string */ function hide_mobile(string $mobile): string { return substr_replace($mobile, '****', 3, 4); } function getHost(){ return (isset($_SERVER['REQUEST_SCHEME'])&&!empty($_SERVER['REQUEST_SCHEME']) ? $_SERVER['REQUEST_SCHEME'] : "https")."://".$_SERVER['HTTP_HOST']; } function getUrl($value, $host = ''){ if (strpos($value, "http") !== false) { return $value; } $host = $host ? $host : getHost(); return $value ? $host."/".$value : ""; } function getUrlValue($value, $host = '', $storage = ""){ if (strpos($value, "http") !== false) { return $value; } $host = $host ? $host : getHost(); if ($storage == 'local') { return uploads_url() .$value; } else { return $value ? $host."/".$value : ""; } } function calc_time($startTime, $endTime) { $diffTime = ($endTime - $startTime); if ($diffTime > 3600) { return ""; } return date('i分钟s秒', (3600 - $diffTime)); } if (!function_exists('downLoadExcel')){ /** * 导出excel * @param $name excel名称 * @param $titles 标题 [['name'=>'姓名'],['gender'=>'性别']] * @param array $data * @throws \PhpOffice\PhpSpreadsheet\Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception */ function downLoadExcel($name, $titles, $data=[]) { $count = count($titles); //计算表头数量 $spreadsheet = new Spreadsheet(); $styleArray = [ 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_CENTER_CONTINUOUS, 'vertical' => Alignment::VERTICAL_CENTER, 'wrapText' => true, ], ]; $sheet = $spreadsheet->getActiveSheet(); for ($i = 65; $i < $count + 65; $i++) { //数字转字母从65开始,循环设置表头 $sheet->getStyle(strtoupper(chr($i)))->applyFromArray($styleArray); $sheet->getCell(strtoupper(chr($i)).'1')->getStyle()->getFont()->setBold(true); $index = $i - 65; $sheet->setCellValue(strtoupper(chr($i)) . '1', $titles[$index][key($titles[$index])] ); } /*--------------开始从数据库提取信息插入Excel表中------------------*/ foreach ($data as $key => $item) { //循环设置单元格: //$key+2,因为第一行是表头,所以写到表格时 从第二行开始写 for ($i = 65; $i < $count + 65; $i++) { //数字转字母从65开始: $sheet->setCellValue(strtoupper(chr($i)) . ($key + 2),$item[key($titles[$i - 65])]); $spreadsheet->getActiveSheet()->getColumnDimension(strtoupper(chr($i)))->setAutoSize(true); } } header('Content-Type: application/vnd.ms-excel'); header('Content-Disposition: attachment;filename="' . $name . '.xlsx"'); header('Cache-Control: max-age=0'); $writer = IOFactory::createWriter($spreadsheet,'Xlsx'); $writer->save('php://output'); //删除清空 $spreadsheet->disconnectWorksheets(); unset($spreadsheet); exit; } } /** * CURL请求 * @param $url 请求url地址 * @param $method 请求方法 get post * @param null $postfields post数据数组 * @param array $headers 请求header信息 * @param bool|false $debug 调试开启 默认false * @return mixed */ //Modified by Shayne Song to solve problem that OFPAY video vip card buying interface need 15 seconds to return result on 2018/03/19. function httpRequest($url, $method="GET", $postfields = null, $headers = array(), $debug = false, $timeout = 10) { $method = strtoupper($method); $ci = curl_init(); /* Curl settings */ curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); curl_setopt($ci, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0"); curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 60); /* 在发起连接前等待的时间,如果设置为0,则无限等待 */ curl_setopt($ci, CURLOPT_TIMEOUT, $timeout); /* 设置cURL允许执行的最长秒数 */ curl_setopt($ci, CURLOPT_RETURNTRANSFER, true); switch ($method) { case "POST": curl_setopt($ci, CURLOPT_POST, true); if (!empty($postfields)) { $tmpdatastr = is_array($postfields) ? http_build_query($postfields) : $postfields; curl_setopt($ci, CURLOPT_POSTFIELDS, $tmpdatastr); } break; default: curl_setopt($ci, CURLOPT_CUSTOMREQUEST, $method); /* //设置请求方式 */ break; } $ssl = preg_match('/^https:\/\//i',$url) ? TRUE : FALSE; curl_setopt($ci, CURLOPT_URL, $url); if($ssl){ curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, FALSE); // 不从证书中检查SSL加密算法是否存在 } //curl_setopt($ci, CURLOPT_HEADER, true); /*启用时会将头文件的信息作为数据流输出*/ curl_setopt($ci, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ci, CURLOPT_MAXREDIRS, 2);/*指定最多的HTTP重定向的数量,这个选项是和CURLOPT_FOLLOWLOCATION一起使用的*/ curl_setopt($ci, CURLOPT_HTTPHEADER, $headers); curl_setopt($ci, CURLINFO_HEADER_OUT, true); /*curl_setopt($ci, CURLOPT_COOKIE, $Cookiestr); * *COOKIE带过去** */ $response = curl_exec($ci); $requestinfo = curl_getinfo($ci); $http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE); $curl_error = curl_errno($ci); if($curl_error){ Log::error("ERROR_CODE:{$curl_error} | URL:".$url.' | postfields:'.json_encode($postfields),'curl_error'); //sys_log("ERROR_CODE:{$curl_error} | URL:".$url.' | postfields:'.json_encode($postfields),'curl_error'); //\app\common\util\ErrorAlert::curlWarning($url,$curl_error); } if ($debug) { echo "=====post data======\r\n"; var_dump($postfields); echo "=====info===== \r\n"; print_r($requestinfo); echo "=====response=====\r\n"; print_r($response); } curl_close($ci); return json_decode($response, true); //return array($http_code, $response,$requestinfo); } /** * 获取加价之后的成本价 * [getGoodsCostPrice description] * @param [type] $cost_price [description] * @param [type] $rate [description] * @return [type] [description] */ function getGoodsCostAndProfitAndProfitRate($net_price, $cost_price, $rate){ if ($rate > 0) { $cost_price = round($cost_price / (1 - ($rate / 100)), 0); } $profit = (float)$net_price - (float)$cost_price; $profit_rate = (float)$net_price > 0 ? bcmul(bcdiv((string)$profit, (string)$net_price, 4), (string)100, 2) : 0.00; return [$cost_price, $profit, $profit_rate]; } /** * 抓取京东商品信息 * [getJdGoodsBySku description] * @param [type] $skus [description] * @return [type] [description] */ function getJdGoodsBySku($skus){ $sku = implode(",", $skus); $url = "http://47.98.251.206:8811/api/skus/info?skus=".$sku; $data = httpRequest($url, "GET", null, [], false, 30); if ($data['code'] != 0 || !$data['data']) { return []; } $data = $data['data']; foreach ($data as &$item) { $content = ""; if (isset($item['infoImages']) && $item['infoImages']) { foreach ($item['infoImages'] as $value) { if (strpos($value, "http") !== false) { $content .= '

'; } else { if (strpos($value, "//") !== false) { $content .= '

'; } else { $content .= '

'; } } } $item['content'] = $content; } $goods_images = []; //写入主图到数据库 if ($item['mainImages']) { foreach ($item['mainImages'] as $image) { $goods_images[] = [ 'preview_url' => $image, 'file_id' => 0, ]; } } $item['goods_images'] = $goods_images; } $data = array_column($data, null, "skuId"); return $data; }