1596 lines
53 KiB
PHP
1596 lines
53 KiB
PHP
<?php
|
||
|
||
// 公共助手函数
|
||
|
||
use think\exception\HttpResponseException;
|
||
use think\Response;
|
||
// 引入 Pinyin 类
|
||
use Overtrue\Pinyin\Pinyin;
|
||
use think\Config;
|
||
use think\Db;
|
||
use think\Request;
|
||
if (!function_exists('__')) {
|
||
|
||
/**
|
||
* 获取语言变量值
|
||
* @param string $name 语言变量名
|
||
* @param array $vars 动态变量值
|
||
* @param string $lang 语言
|
||
* @return mixed
|
||
*/
|
||
function __($name, $vars = [], $lang = '')
|
||
{
|
||
if (is_numeric($name) || !$name) {
|
||
return $name;
|
||
}
|
||
if (!is_array($vars)) {
|
||
$vars = func_get_args();
|
||
array_shift($vars);
|
||
$lang = '';
|
||
}
|
||
return \think\Lang::get($name, $vars, $lang);
|
||
}
|
||
}
|
||
|
||
if (!function_exists('format_bytes')) {
|
||
|
||
/**
|
||
* 将字节转换为可读文本
|
||
* @param int $size 大小
|
||
* @param string $delimiter 分隔符
|
||
* @param int $precision 小数位数
|
||
* @return string
|
||
*/
|
||
function format_bytes($size, $delimiter = '', $precision = 2)
|
||
{
|
||
$units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
|
||
for ($i = 0; $size >= 1024 && $i < 6; $i++) {
|
||
$size /= 1024;
|
||
}
|
||
return round($size, $precision) . $delimiter . $units[$i];
|
||
}
|
||
}
|
||
|
||
if (!function_exists('datetime')) {
|
||
|
||
/**
|
||
* 将时间戳转换为日期时间
|
||
* @param int $time 时间戳
|
||
* @param string $format 日期时间格式
|
||
* @return string
|
||
*/
|
||
function datetime($time, $format = 'Y-m-d H:i:s')
|
||
{
|
||
$time = is_numeric($time) ? $time : strtotime($time);
|
||
return date($format, $time);
|
||
}
|
||
}
|
||
|
||
if (!function_exists('human_date')) {
|
||
|
||
/**
|
||
* 获取语义化时间
|
||
* @param int $time 时间
|
||
* @param int $local 本地时间
|
||
* @return string
|
||
*/
|
||
function human_date($time, $local = null)
|
||
{
|
||
return \fast\Date::human($time, $local);
|
||
}
|
||
}
|
||
|
||
if (!function_exists('cdnurl')) {
|
||
|
||
/**
|
||
* 获取上传资源的CDN的地址
|
||
* @param string $url 资源相对地址
|
||
* @param boolean $domain 是否显示域名 或者直接传入域名
|
||
* @return string
|
||
*/
|
||
function cdnurl($url, $domain = false)
|
||
{
|
||
$regex = "/^((?:[a-z]+:)?\/\/|data:image\/)(.*)/i";
|
||
$cdnurl = \think\Config::get('upload.cdnurl');
|
||
if (is_bool($domain) || stripos($cdnurl, '/') === 0) {
|
||
$url = preg_match($regex, $url) || ($cdnurl && stripos($url, $cdnurl) === 0) ? $url : $cdnurl . $url;
|
||
}
|
||
if ($domain && !preg_match($regex, $url)) {
|
||
$domain = is_bool($domain) ? request()->domain() : $domain;
|
||
$url = $domain . $url;
|
||
}
|
||
return $url;
|
||
}
|
||
}
|
||
|
||
|
||
if (!function_exists('is_really_writable')) {
|
||
|
||
/**
|
||
* 判断文件或文件夹是否可写
|
||
* @param string $file 文件或目录
|
||
* @return bool
|
||
*/
|
||
function is_really_writable($file)
|
||
{
|
||
if (DIRECTORY_SEPARATOR === '/') {
|
||
return is_writable($file);
|
||
}
|
||
if (is_dir($file)) {
|
||
$file = rtrim($file, '/') . '/' . md5(mt_rand());
|
||
if (($fp = @fopen($file, 'ab')) === false) {
|
||
return false;
|
||
}
|
||
fclose($fp);
|
||
@chmod($file, 0777);
|
||
@unlink($file);
|
||
return true;
|
||
} elseif (!is_file($file) or ($fp = @fopen($file, 'ab')) === false) {
|
||
return false;
|
||
}
|
||
fclose($fp);
|
||
return true;
|
||
}
|
||
}
|
||
|
||
if (!function_exists('rmdirs')) {
|
||
|
||
/**
|
||
* 删除文件夹
|
||
* @param string $dirname 目录
|
||
* @param bool $withself 是否删除自身
|
||
* @return boolean
|
||
*/
|
||
function rmdirs($dirname, $withself = true)
|
||
{
|
||
if (!is_dir($dirname)) {
|
||
return false;
|
||
}
|
||
$files = new RecursiveIteratorIterator(
|
||
new RecursiveDirectoryIterator($dirname, RecursiveDirectoryIterator::SKIP_DOTS),
|
||
RecursiveIteratorIterator::CHILD_FIRST
|
||
);
|
||
|
||
foreach ($files as $fileinfo) {
|
||
$todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink');
|
||
$todo($fileinfo->getRealPath());
|
||
}
|
||
if ($withself) {
|
||
@rmdir($dirname);
|
||
}
|
||
return true;
|
||
}
|
||
}
|
||
|
||
if (!function_exists('copydirs')) {
|
||
|
||
/**
|
||
* 复制文件夹
|
||
* @param string $source 源文件夹
|
||
* @param string $dest 目标文件夹
|
||
*/
|
||
function copydirs($source, $dest)
|
||
{
|
||
if (!is_dir($dest)) {
|
||
mkdir($dest, 0755, true);
|
||
}
|
||
foreach (
|
||
$iterator = new RecursiveIteratorIterator(
|
||
new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS),
|
||
RecursiveIteratorIterator::SELF_FIRST
|
||
) as $item
|
||
) {
|
||
if ($item->isDir()) {
|
||
$sontDir = $dest . DS . $iterator->getSubPathName();
|
||
if (!is_dir($sontDir)) {
|
||
mkdir($sontDir, 0755, true);
|
||
}
|
||
} else {
|
||
copy($item, $dest . DS . $iterator->getSubPathName());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!function_exists('mb_ucfirst')) {
|
||
function mb_ucfirst($string)
|
||
{
|
||
return mb_strtoupper(mb_substr($string, 0, 1)) . mb_strtolower(mb_substr($string, 1));
|
||
}
|
||
}
|
||
|
||
if (!function_exists('addtion')) {
|
||
|
||
/**
|
||
* 附加关联字段数据
|
||
* @param array $items 数据列表
|
||
* @param mixed $fields 渲染的来源字段
|
||
* @return array
|
||
*/
|
||
function addtion($items, $fields)
|
||
{
|
||
if (!$items || !$fields) {
|
||
return $items;
|
||
}
|
||
$fieldsArr = [];
|
||
if (!is_array($fields)) {
|
||
$arr = explode(',', $fields);
|
||
foreach ($arr as $k => $v) {
|
||
$fieldsArr[$v] = ['field' => $v];
|
||
}
|
||
} else {
|
||
foreach ($fields as $k => $v) {
|
||
if (is_array($v)) {
|
||
$v['field'] = $v['field'] ?? $k;
|
||
} else {
|
||
$v = ['field' => $v];
|
||
}
|
||
$fieldsArr[$v['field']] = $v;
|
||
}
|
||
}
|
||
foreach ($fieldsArr as $k => &$v) {
|
||
$v = is_array($v) ? $v : ['field' => $v];
|
||
$v['display'] = $v['display'] ?? str_replace(['_ids', '_id'], ['_names', '_name'], $v['field']);
|
||
$v['primary'] = $v['primary'] ?? '';
|
||
$v['column'] = $v['column'] ?? 'name';
|
||
$v['model'] = $v['model'] ?? '';
|
||
$v['table'] = $v['table'] ?? '';
|
||
$v['name'] = $v['name'] ?? str_replace(['_ids', '_id'], '', $v['field']);
|
||
}
|
||
unset($v);
|
||
$ids = [];
|
||
$fields = array_keys($fieldsArr);
|
||
foreach ($items as $k => $v) {
|
||
foreach ($fields as $m => $n) {
|
||
if (isset($v[$n])) {
|
||
$ids[$n] = array_merge(isset($ids[$n]) && is_array($ids[$n]) ? $ids[$n] : [], explode(',', $v[$n]));
|
||
}
|
||
}
|
||
}
|
||
$result = [];
|
||
foreach ($fieldsArr as $k => $v) {
|
||
if ($v['model']) {
|
||
$model = new $v['model'];
|
||
} else {
|
||
$model = $v['name'] ? \think\Db::name($v['name']) : \think\Db::table($v['table']);
|
||
}
|
||
$primary = $v['primary'] ? $v['primary'] : $model->getPk();
|
||
$result[$v['field']] = isset($ids[$v['field']]) ? $model->where($primary, 'in', $ids[$v['field']])->column($v['column'], $primary) : [];
|
||
}
|
||
|
||
foreach ($items as $k => &$v) {
|
||
foreach ($fields as $m => $n) {
|
||
if (isset($v[$n])) {
|
||
$curr = array_flip(explode(',', $v[$n]));
|
||
|
||
$linedata = array_intersect_key($result[$n], $curr);
|
||
$v[$fieldsArr[$n]['display']] = $fieldsArr[$n]['column'] == '*' ? $linedata : implode(',', $linedata);
|
||
}
|
||
}
|
||
}
|
||
return $items;
|
||
}
|
||
}
|
||
|
||
if (!function_exists('var_export_short')) {
|
||
|
||
/**
|
||
* 使用短标签打印或返回数组结构
|
||
* @param mixed $data
|
||
* @param boolean $return 是否返回数据
|
||
* @return string
|
||
*/
|
||
function var_export_short($data, $return = true)
|
||
{
|
||
return var_export($data, $return);
|
||
$replaced = [];
|
||
$count = 0;
|
||
|
||
//判断是否是对象
|
||
if (is_resource($data) || is_object($data)) {
|
||
return var_export($data, $return);
|
||
}
|
||
|
||
//判断是否有特殊的键名
|
||
$specialKey = false;
|
||
array_walk_recursive($data, function (&$value, &$key) use (&$specialKey) {
|
||
if (is_string($key) && (stripos($key, "\n") !== false || stripos($key, "array (") !== false)) {
|
||
$specialKey = true;
|
||
}
|
||
});
|
||
if ($specialKey) {
|
||
return var_export($data, $return);
|
||
}
|
||
array_walk_recursive($data, function (&$value, &$key) use (&$replaced, &$count, &$stringcheck) {
|
||
if (is_object($value) || is_resource($value)) {
|
||
$replaced[$count] = var_export($value, true);
|
||
$value = "##<{$count}>##";
|
||
} else {
|
||
if (is_string($value) && (stripos($value, "\n") !== false || stripos($value, "array (") !== false)) {
|
||
$index = array_search($value, $replaced);
|
||
if ($index === false) {
|
||
$replaced[$count] = var_export($value, true);
|
||
$value = "##<{$count}>##";
|
||
} else {
|
||
$value = "##<{$index}>##";
|
||
}
|
||
}
|
||
}
|
||
$count++;
|
||
});
|
||
|
||
$dump = var_export($data, true);
|
||
|
||
$dump = preg_replace('#(?:\A|\n)([ ]*)array \(#i', '[', $dump); // Starts
|
||
$dump = preg_replace('#\n([ ]*)\),#', "\n$1],", $dump); // Ends
|
||
$dump = preg_replace('#=> \[\n\s+\],\n#', "=> [],\n", $dump); // Empties
|
||
$dump = preg_replace('#\)$#', "]", $dump); //End
|
||
|
||
if ($replaced) {
|
||
$dump = preg_replace_callback("/'##<(\d+)>##'/", function ($matches) use ($replaced) {
|
||
return $replaced[$matches[1]] ?? "''";
|
||
}, $dump);
|
||
}
|
||
|
||
if ($return === true) {
|
||
return $dump;
|
||
} else {
|
||
echo $dump;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!function_exists('letter_avatar')) {
|
||
/**
|
||
* 首字母头像
|
||
* @param $text
|
||
* @return string
|
||
*/
|
||
function letter_avatar($text)
|
||
{
|
||
$total = unpack('L', hash('adler32', $text, true))[1];
|
||
$hue = $total % 360;
|
||
list($r, $g, $b) = hsv2rgb($hue / 360, 0.3, 0.9);
|
||
|
||
$bg = "rgb({$r},{$g},{$b})";
|
||
$color = "#ffffff";
|
||
$first = mb_strtoupper(mb_substr($text, 0, 1));
|
||
$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>');
|
||
$value = 'data:image/svg+xml;base64,' . $src;
|
||
return $value;
|
||
}
|
||
}
|
||
|
||
if (!function_exists('hsv2rgb')) {
|
||
function hsv2rgb($h, $s, $v)
|
||
{
|
||
$r = $g = $b = 0;
|
||
|
||
$i = floor($h * 6);
|
||
$f = $h * 6 - $i;
|
||
$p = $v * (1 - $s);
|
||
$q = $v * (1 - $f * $s);
|
||
$t = $v * (1 - (1 - $f) * $s);
|
||
|
||
switch ($i % 6) {
|
||
case 0:
|
||
$r = $v;
|
||
$g = $t;
|
||
$b = $p;
|
||
break;
|
||
case 1:
|
||
$r = $q;
|
||
$g = $v;
|
||
$b = $p;
|
||
break;
|
||
case 2:
|
||
$r = $p;
|
||
$g = $v;
|
||
$b = $t;
|
||
break;
|
||
case 3:
|
||
$r = $p;
|
||
$g = $q;
|
||
$b = $v;
|
||
break;
|
||
case 4:
|
||
$r = $t;
|
||
$g = $p;
|
||
$b = $v;
|
||
break;
|
||
case 5:
|
||
$r = $v;
|
||
$g = $p;
|
||
$b = $q;
|
||
break;
|
||
}
|
||
|
||
return [
|
||
floor($r * 255),
|
||
floor($g * 255),
|
||
floor($b * 255)
|
||
];
|
||
}
|
||
}
|
||
|
||
if (!function_exists('check_nav_active')) {
|
||
/**
|
||
* 检测会员中心导航是否高亮
|
||
*/
|
||
function check_nav_active($url, $classname = 'active')
|
||
{
|
||
$auth = \app\common\library\Auth::instance();
|
||
$requestUrl = $auth->getRequestUri();
|
||
$url = ltrim($url, '/');
|
||
return $requestUrl === str_replace(".", "/", $url) ? $classname : '';
|
||
}
|
||
}
|
||
|
||
if (!function_exists('check_cors_request')) {
|
||
/**
|
||
* 跨域检测
|
||
*/
|
||
function check_cors_request()
|
||
{
|
||
if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN'] && config('fastadmin.cors_request_domain')) {
|
||
$info = parse_url($_SERVER['HTTP_ORIGIN']);
|
||
$domainArr = explode(',', config('fastadmin.cors_request_domain'));
|
||
$domainArr[] = request()->host(true);
|
||
if (in_array("*", $domainArr) || in_array($_SERVER['HTTP_ORIGIN'], $domainArr) || (isset($info['host']) && in_array($info['host'], $domainArr))) {
|
||
header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
|
||
} else {
|
||
$response = Response::create('跨域检测无效', 'html', 403);
|
||
throw new HttpResponseException($response);
|
||
}
|
||
|
||
header('Access-Control-Allow-Credentials: true');
|
||
header('Access-Control-Max-Age: 86400');
|
||
|
||
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
|
||
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
|
||
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
|
||
}
|
||
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
|
||
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
|
||
}
|
||
$response = Response::create('', 'html');
|
||
throw new HttpResponseException($response);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!function_exists('xss_clean')) {
|
||
/**
|
||
* 清理XSS
|
||
*/
|
||
function xss_clean($content, $is_image = false)
|
||
{
|
||
return \app\common\library\Security::instance()->xss_clean($content, $is_image);
|
||
}
|
||
}
|
||
|
||
if (!function_exists('url_clean')) {
|
||
/**
|
||
* 清理URL
|
||
*/
|
||
function url_clean($url)
|
||
{
|
||
if (!check_url_allowed($url)) {
|
||
return '';
|
||
}
|
||
return xss_clean($url);
|
||
}
|
||
}
|
||
|
||
if (!function_exists('check_ip_allowed')) {
|
||
/**
|
||
* 检测IP是否允许
|
||
* @param string $ip IP地址
|
||
*/
|
||
function check_ip_allowed($ip = null)
|
||
{
|
||
$ip = is_null($ip) ? request()->ip() : $ip;
|
||
$forbiddenipArr = config('site.forbiddenip');
|
||
$forbiddenipArr = !$forbiddenipArr ? [] : $forbiddenipArr;
|
||
$forbiddenipArr = is_array($forbiddenipArr) ? $forbiddenipArr : array_filter(explode("\n", str_replace("\r\n", "\n", $forbiddenipArr)));
|
||
if ($forbiddenipArr && \Symfony\Component\HttpFoundation\IpUtils::checkIp($ip, $forbiddenipArr)) {
|
||
$response = Response::create('请求无权访问', 'html', 403);
|
||
throw new HttpResponseException($response);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!function_exists('check_url_allowed')) {
|
||
/**
|
||
* 检测URL是否允许
|
||
* @param string $url URL
|
||
* @return bool
|
||
*/
|
||
function check_url_allowed($url = '')
|
||
{
|
||
//允许的主机列表
|
||
$allowedHostArr = [
|
||
strtolower(request()->host())
|
||
];
|
||
|
||
if (empty($url)) {
|
||
return true;
|
||
}
|
||
|
||
//如果是站内相对链接则允许
|
||
if (preg_match("/^[\/a-z][a-z0-9][a-z0-9\.\/]+((\?|#).*)?\$/i", $url) && substr($url, 0, 2) !== '//') {
|
||
return true;
|
||
}
|
||
|
||
//如果是站外链接则需要判断HOST是否允许
|
||
if (preg_match("/((http[s]?:\/\/)+(?>[a-z\-0-9]{2,}\.){1,}[a-z]{2,8})(?:\s|\/)/i", $url)) {
|
||
$chkHost = parse_url(strtolower($url), PHP_URL_HOST);
|
||
if ($chkHost && in_array($chkHost, $allowedHostArr)) {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
}
|
||
|
||
if (!function_exists('build_suffix_image')) {
|
||
/**
|
||
* 生成文件后缀图片
|
||
* @param string $suffix 后缀
|
||
* @param null $background
|
||
* @return string
|
||
*/
|
||
function build_suffix_image($suffix, $background = null)
|
||
{
|
||
$suffix = mb_substr(strtoupper($suffix), 0, 4);
|
||
$total = unpack('L', hash('adler32', $suffix, true))[1];
|
||
$hue = $total % 360;
|
||
list($r, $g, $b) = hsv2rgb($hue / 360, 0.3, 0.9);
|
||
|
||
$background = $background ? $background : "rgb({$r},{$g},{$b})";
|
||
|
||
$icon = <<<EOT
|
||
<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">
|
||
<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"/>
|
||
<path style="fill:#B0B7BD;" d="M384,128h96L352,0v96C352,113.6,366.4,128,384,128z"/>
|
||
<polygon style="fill:#CAD1D8;" points="480,224 384,128 480,128 "/>
|
||
<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"/>
|
||
<path style="fill:#CAD1D8;" d="M400,432H96v16h304c8.8,0,16-7.2,16-16v-16C416,424.8,408.8,432,400,432z"/>
|
||
<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>
|
||
</svg>
|
||
EOT;
|
||
return $icon;
|
||
}
|
||
}
|
||
/**
|
||
* 格式化数字
|
||
* @param int $number 要格式化的数字
|
||
* @return string 格式化后的字符串
|
||
*/
|
||
function formatNumber($number) {
|
||
$length = strlen($number); //数字长度
|
||
if($length > 8){ //亿单位
|
||
$str = substr_replace(strstr($number,substr($number,-7),' '),'.',-1,0)."亿";
|
||
}elseif($length >4){ //万单位
|
||
//截取前俩为
|
||
$str = substr_replace(strstr($number,substr($number,-3),' '),'.',-1,0)."万";
|
||
}elseif($length >3){ //千单位
|
||
//截取前俩为
|
||
$str = substr_replace(strstr($number,substr($number,-2),' '),'.',-1,0)."K";
|
||
}else{
|
||
return $number;
|
||
}
|
||
return $str;
|
||
}
|
||
// 公共接口调用方法
|
||
function callApi($url, $cookie = '', $userAgent = '')
|
||
{
|
||
$curl = curl_init($url);
|
||
|
||
// 设置选项
|
||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // 将响应保存到变量而不是直接输出
|
||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向
|
||
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, false); //这个是重点。
|
||
// 设置请求头部信息
|
||
$headers = [
|
||
'Content-Type: application/json',
|
||
'Accept: application/json',
|
||
'Access-Control-Allow-Origin: *', // 允许跨域请求
|
||
];
|
||
if (!empty($userAgent)) {
|
||
$headers[] = "User-Agent: {$userAgent}";
|
||
}
|
||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||
|
||
// 设置 Cookie
|
||
if (!empty($cookie)) {
|
||
curl_setopt($curl, CURLOPT_COOKIE, $cookie);
|
||
}
|
||
|
||
$response = curl_exec($curl);
|
||
|
||
if(curl_errno($curl)) {
|
||
$error_message = curl_error($curl);
|
||
}
|
||
// 获取响应状态码
|
||
$statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||
curl_close($curl);
|
||
// 返回响应结果
|
||
if ($statusCode >= 200 && $statusCode < 300 && !empty($response)) {
|
||
return $response;
|
||
} else {
|
||
return false;
|
||
// return $response;
|
||
}
|
||
}
|
||
// 数据写入文件txt方法
|
||
function writeToTxt($filePath, $data)
|
||
{
|
||
if (file_exists($filePath)) {
|
||
// 如果文件存在,覆盖写入内容
|
||
if (file_put_contents($filePath, $data) !== false) {
|
||
return true; // 写入成功,返回 true
|
||
} else {
|
||
return false; // 写入失败,返回 false
|
||
}
|
||
} else {
|
||
// 如果文件不存在,创建并写入
|
||
$fileHandle = fopen($filePath, "w+");
|
||
if ($fileHandle) {
|
||
if (fwrite($fileHandle, $data . "\n") !== false) {
|
||
fclose($fileHandle); // 关闭文件指针
|
||
return true; // 写入成功,返回 true
|
||
} else {
|
||
fclose($fileHandle); // 关闭文件指针
|
||
return false; // 写入失败,返回 false
|
||
}
|
||
} else {
|
||
return false; // 创建文件失败,返回 false
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* 高亮显示关键词
|
||
* @param string $text 文章内容
|
||
* @param array $keywords 关键词数组
|
||
* @return string 高亮显示后的文章内容
|
||
*/
|
||
function words($text, $keyword) {
|
||
$highlightedString = str_replace($keyword, '<em style="color:red;font-style: normal">'.$keyword.'</em>', $text);
|
||
return $highlightedString;
|
||
}
|
||
// 替换字符串指定字符
|
||
function replaceComma($inputString,$str = ',',$str1 = '、') {
|
||
$outputString = str_replace($str,$str1, $inputString);
|
||
return $outputString;
|
||
}
|
||
// 分割
|
||
function splitString($string, $delimiters) {
|
||
$pattern = '/[' . preg_quote(implode("", $delimiters), '/') . ']+/';
|
||
return preg_split($pattern, $string, -1, PREG_SPLIT_NO_EMPTY);
|
||
}
|
||
// 将15位身份证号码改成18位
|
||
function convertTo18IDCard($idCard15) {
|
||
$idCard17 = substr($idCard15, 0, 6) . '19' . substr($idCard15, 6);
|
||
$idCard17Array = str_split($idCard17);
|
||
$wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
|
||
$vi = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
|
||
$sum = 0;
|
||
for ($i = 0; $i < 17; $i++) {
|
||
$sum += $idCard17Array[$i] * $wi[$i];
|
||
}
|
||
$mod = $sum % 11;
|
||
$idCard18 = $idCard17 . $vi[$mod];
|
||
|
||
return $idCard18;
|
||
}
|
||
/**
|
||
* 人民币小写转大写
|
||
*
|
||
* @param string $number 待处理数值
|
||
* @param bool $is_round 小数是否四舍五入,默认"四舍五入"
|
||
* @param string $int_unit 币种单位,默认"元"
|
||
* @return string
|
||
*/
|
||
function rmbToUpperCase($num = 0, $is_round = false, $int_unit = '元') {
|
||
$chs = array (0, '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖');
|
||
$uni = array ('', '拾', '佰', '仟' );
|
||
$dec_uni = array ('角', '分' );
|
||
$exp = array ('','万','亿');
|
||
$res = '';
|
||
// 以 元为单位分割
|
||
$parts = explode ( '.', $num, 2 );
|
||
$int = isset ( $parts [0] ) ? strval ( $parts [0] ) : 0;
|
||
$dec = isset ( $parts [1] ) ? strval ( $parts [1] ) : '';
|
||
// 处理小数点
|
||
$dec_len = strlen ( $dec );
|
||
if (isset ( $parts [1] ) && $dec_len > 2) {
|
||
$dec = $is_round ? substr ( strrchr ( strval ( round ( floatval ( "0." . $dec ), 2 ) ), '.' ), 1 ) : substr ( $parts [1], 0, 2 );
|
||
}
|
||
// number= 0.00时,直接返回 0
|
||
if (empty ( $int ) && empty ( $dec )) {
|
||
return '零';
|
||
}
|
||
|
||
// 整数部分 从右向左
|
||
for($i = strlen ( $int ) - 1, $t = 0; $i >= 0; $t++) {
|
||
$str = '';
|
||
// 每4字为一段进行转化
|
||
// for($j = 0; $j < 4 && $i >= 0; $j ++, $i --) {
|
||
// $u = $int{$i} > 0 ? $uni [$j] : '';
|
||
// $str = $chs[$int[$i]] . $u . $str;
|
||
// }
|
||
for ($j = 0; $j < 4 && $i >= 0; $j++, $i--) {
|
||
$u = $int[$i] > 0 ? $uni[$j] : '';
|
||
$str = $chs[$int[$i]] . $u . $str;
|
||
}
|
||
$str = rtrim ( $str, '0' );
|
||
$str = preg_replace ( "/0+/", "零", $str );
|
||
$u2 = $str != '' ? $exp [$t] : '';
|
||
$res = $str . $u2 . $res;
|
||
}
|
||
$dec = rtrim ( $dec, '0' );
|
||
// 小数部分 从左向右
|
||
if (!empty ( $dec )) {
|
||
$res .= $int_unit;
|
||
$cnt = strlen ( $dec );
|
||
for ($i = 0; $i < $cnt; $i++) {
|
||
$u = $dec[$i] > 0 ? $dec_uni[$i] : ''; // 非0的数字后面添加单位
|
||
$res .= $chs[$dec[$i]] . $u;
|
||
}
|
||
if ($cnt == 1) $res .= '整';
|
||
$res = rtrim ( $res, '0' ); // 去掉末尾的0
|
||
$res = preg_replace ( "/0+/", "零", $res ); // 替换多个连续的0
|
||
} else {
|
||
$res .= $int_unit . '整';
|
||
}
|
||
return $res;
|
||
}
|
||
// 阿拉伯数字转美元大写
|
||
function numberToWords($number) {
|
||
$decimal = round($number - ($no = floor($number)), 2) * 100;
|
||
$hundred = null;
|
||
$digits_length = strlen($no);
|
||
$i = 0;
|
||
$str = array();
|
||
$words = array(0 => '', 1 => 'ONE', 2 => 'TWO',
|
||
3 => 'THREE', 4 => 'FOUR', 5 => 'FIVE', 6 => 'SIX',
|
||
7 => 'SEVEN', 8 => 'EIGHT', 9 => 'NINE',
|
||
10 => 'TEN', 11 => 'ELEVEN', 12 => 'TWELVE',
|
||
13 => 'THIRTEEN', 14 => 'FOURTEEN',
|
||
15 => 'FIFTEEN', 16 => 'SIXTEEN', 17 => 'SEVENTEEN',
|
||
18 => 'EIGHTEEN', 19 => 'NINETEEN', 20 => 'TWENTY',
|
||
30 => 'THIRTY', 40 => 'FORTY', 50 => 'FIFTY',
|
||
60 => 'SIXTY', 70 => 'SEVENTY',
|
||
80 => 'EIGHTY', 90 => 'NINETY');
|
||
$digits = array('', 'HUNDRED', 'THOUSAND', 'LAC', 'CRORE');
|
||
|
||
while ($i < $digits_length) {
|
||
$divider = ($i == 2) ? 10 : 100;
|
||
$number = floor($no % $divider);
|
||
$no = floor($no / $divider);
|
||
$i += ($divider == 10) ? 1 : 2;
|
||
|
||
if ($number) {
|
||
$plural = (($counter = count($str)) && $number > 9) ? 'S' : null;
|
||
$hundred = ($counter == 1 && $str[0]) ? ' AND ' : null;
|
||
$str [] = ($number < 21) ? $words[$number] .
|
||
" " . $digits[$counter] . $plural . " " . $hundred
|
||
:
|
||
$words[floor($number / 10) * 10]
|
||
. " " . $words[$number % 10] . " "
|
||
. $digits[$counter] . $plural . " " . $hundred;
|
||
} else $str[] = null;
|
||
}
|
||
|
||
$str = array_reverse($str);
|
||
$result = implode('', $str);
|
||
|
||
if ($decimal > 0) {
|
||
$result .= " AND CENTS ";
|
||
if ($decimal < 10) {
|
||
$result .= $words[$decimal];
|
||
} else {
|
||
$result .= $words[floor($decimal / 10) * 10];
|
||
$result .= " " . $words[$decimal % 10];
|
||
}
|
||
}
|
||
|
||
return 'SAY US DOLLARS ' . $result . ' ONLY';
|
||
}
|
||
// 长度单位换算
|
||
function lengthConversion($value, $unit) {
|
||
// 定义单位之间的换算关系
|
||
$conversionTable = [
|
||
'km' => 1000, // 千米
|
||
'm' => 1, // 米
|
||
'dm' => 0.1, // 分米
|
||
'cm' => 0.01, // 厘米
|
||
'li' => 500, // 里
|
||
'zhang' => 3.33333, // 丈
|
||
'chi' => 0.33333, // 尺
|
||
'cun' => 0.03333, // 寸
|
||
'fen' => 0.00333, // 分
|
||
'li2' => 0.000333, // 厘
|
||
'nmi' => 1852, // 海里
|
||
'fathom' => 1.8288, // 英寻
|
||
'mile' => 1609.344, // 英里
|
||
'fur' => 201.168, // 弗隆
|
||
'yd' => 0.9144, // 码
|
||
'ft' => 0.3048, // 英尺
|
||
'ins' => 0.0254, // 英寸
|
||
'mm' => 0.001, // 毫米
|
||
'um' => 0.000001 // 微米
|
||
];
|
||
|
||
// 转换为转换单位
|
||
$baseValue = $value * $conversionTable[$unit];
|
||
|
||
// 构建输出数组
|
||
$result = [];
|
||
foreach ($conversionTable as $key => $conversionValue) {
|
||
if ($conversionValue === 1) {
|
||
$result[$key] = intval($baseValue);
|
||
} else {
|
||
$result[$key] = round($baseValue / $conversionValue, 8);
|
||
}
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
// 温度单位换算
|
||
function convertTemperature($value, $unit) {
|
||
$result = [];
|
||
|
||
switch ($unit) {
|
||
case 'c':
|
||
// 摄氏度
|
||
$result['c'] = $value;
|
||
// 华氏度
|
||
$result['f'] = ($value * 9/5) + 32;
|
||
// 开氏度
|
||
$result['k'] = $value + 273.15;
|
||
// 兰氏度
|
||
$result['ra'] = ($value + 273.15) * 9/5;
|
||
// 列氏度
|
||
$result['re'] = $value * 4/5;
|
||
break;
|
||
case 'f':
|
||
// 摄氏度
|
||
$result['c'] = ($value - 32) * 5/9;
|
||
// 华氏度
|
||
$result['f'] = $value;
|
||
// 开氏度
|
||
$result['k'] = ($value + 459.67) * 5/9;
|
||
// 兰氏度
|
||
$result['ra'] = $value + 459.67;
|
||
// 列氏度
|
||
$result['re'] = ($value - 32) * 4/9;
|
||
break;
|
||
case 'k':
|
||
// 摄氏度
|
||
$result['c'] = $value - 273.15;
|
||
// 华氏度
|
||
$result['f'] = ($value * 9/5) - 459.67;
|
||
// 开氏度
|
||
$result['k'] = $value;
|
||
// 兰氏度
|
||
$result['ra'] = $value * 9/5;
|
||
// 列氏度
|
||
$result['re'] = ($value - 273.15) * 4/5;
|
||
break;
|
||
case 'ra':
|
||
// 摄氏度
|
||
$result['c'] = ($value - 491.67) * 5/9;
|
||
// 华氏度
|
||
$result['f'] = $value - 459.67;
|
||
// 开氏度
|
||
$result['k'] = $value * 5/9;
|
||
// 兰氏度
|
||
$result['ra'] = $value;
|
||
// 列氏度
|
||
$result['re'] = ($value - 491.67) * 4/9;
|
||
break;
|
||
case 're':
|
||
// 摄氏度
|
||
$result['c'] = $value * 5/4;
|
||
// 华氏度
|
||
$result['f'] = ($value * 9/4) + 32;
|
||
// 开氏度
|
||
$result['k'] = ($value * 5/4) + 273.15;
|
||
// 兰氏度
|
||
$result['ra'] = ($value * 9/4) + 491.67;
|
||
// 列氏度
|
||
$result['re'] = $value;
|
||
break;
|
||
default:
|
||
return false;
|
||
}
|
||
|
||
// 对$result数组中的每个值进行变量转换
|
||
foreach($result as &$item) {
|
||
if (is_numeric($item)) {
|
||
$item = floatval($item);
|
||
|
||
if (floor($item) == $item) {
|
||
$item = intval($item);
|
||
} else {
|
||
$item = round($item, 2);
|
||
}
|
||
}
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
// 功率单位换算
|
||
function convertPower($value, $fromUnit) {
|
||
$units = array(
|
||
'w' => 1, // 瓦特(W)
|
||
'kw' => 1000, // 千瓦(kW)
|
||
'hp' => 735.49875, // 马力(HP)
|
||
'ps' => 735.49875, // 百分力马力(PS)
|
||
'kg' => 9.80665, // 公斤·米/秒(kg·m/s)
|
||
'kcal' => 4186.8, // 千卡/秒(kcal/s)
|
||
'btu' => 1055.056, // 英热单位/秒(Btu/s)
|
||
'ft' => 1.355818, // 英尺·磅/秒(ft·lb/s)
|
||
'j' => 1, // 焦耳/秒(J/s)
|
||
'nm' => 1 // 牛顿·米/秒(N·m/s)
|
||
);
|
||
|
||
if (!isset($units[$fromUnit])) {
|
||
return false; // 无效的单位
|
||
}
|
||
|
||
$results = [];
|
||
foreach ($units as $unit => $conversionFactor) {
|
||
$convertedValue = $value * ($units[$fromUnit] / $conversionFactor);
|
||
|
||
// 转换为 float 类型,并保留小数点后 7 位数字
|
||
$roundedValue = round(floatval($convertedValue), 7);
|
||
$results[$unit] = $roundedValue;
|
||
}
|
||
|
||
return $results;
|
||
}
|
||
// 速度单位换算
|
||
function convertSpeed($value, $fromUnit) {
|
||
$units = array(
|
||
'm' => 1, // 米/秒(m/s)
|
||
'km' => 3.6, // 千米/时(km/h)
|
||
'mach' => 343.2, // 马赫(mach)
|
||
'ins' => 0.0254, // 英寸/秒(in/s)
|
||
'kms' => 1000, // 千米/秒(km/s)
|
||
'c' => 299792458, // 光速(c)
|
||
'mile' => 0.44704, // 英里/时(mile/h)
|
||
'knot' => 0.514444, // 节(knot)
|
||
'ly' => 9.461e+12 // 光年/年(ly/y)
|
||
);
|
||
|
||
$fromUnit = strtolower($fromUnit); // 将输入的单位转换为小写字母
|
||
|
||
if (!isset($units[$fromUnit])) {
|
||
return false; // 无效的单位
|
||
}
|
||
|
||
$results = [];
|
||
foreach ($units as $unit => $conversionFactor) {
|
||
$convertedValue = $value * ($units[$fromUnit] / $conversionFactor);
|
||
|
||
// 使用 sprintf() 函数将结果格式化为字符串,并限定小数点后位数为 12
|
||
$formattedValue = sprintf('%0.12f', $convertedValue);
|
||
$results[$unit] = (float) $formattedValue;
|
||
}
|
||
|
||
return $results;
|
||
}
|
||
// 重量单位换算
|
||
function convertWeight($value, $fromUnit) {
|
||
$conversionTable = [
|
||
'tonne' => 1e6, // 吨
|
||
'kilogram' => 1e3, // 公斤
|
||
'gram' => 1, // 克
|
||
'milligram' => 1e-3, // 毫克
|
||
'shijin' => 500, // 市斤
|
||
'dan' => 50000, // 担
|
||
'liang' => 50, // 两
|
||
'qian' => 5, // 钱
|
||
'jhb' => 373.242, // 金衡磅
|
||
'jhas' => 31.1035, // 金衡盎司
|
||
'dwt' => 1.555174, // 英钱
|
||
'jhgl' => 0.06479891, // 金衡格令
|
||
'ycd' => 1016046.9, // (英制)长吨
|
||
'mdd' => 907184.74, // (美制)短吨
|
||
'cwt' => 50802.345, // 英担
|
||
'cwts' => 45359.237, // 美担
|
||
'ys' => 6350.293, // 英石
|
||
'lb' => 453.59237, // 磅
|
||
'oz' => 28.349523125, // 盎司
|
||
'dr' => 1.7718451953125, // 打兰
|
||
'gl' => 0.06479891 // 格令
|
||
];
|
||
|
||
$fromUnit = strtolower($fromUnit);
|
||
|
||
if (!array_key_exists($fromUnit, $conversionTable)) {
|
||
return false;
|
||
}
|
||
|
||
$fromValue = $value * $conversionTable[$fromUnit];
|
||
|
||
$results = [];
|
||
|
||
foreach ($conversionTable as $toUnit => $conversion) {
|
||
$result = $fromValue / $conversion;
|
||
$results[$toUnit] = $result;
|
||
}
|
||
|
||
return $results;
|
||
}
|
||
// 面积单位换算
|
||
function convertArea($value, $unit)
|
||
{
|
||
// 定义各单位与平方米的换算关系
|
||
$conversion = [
|
||
'km2' => 1, // 平方千米
|
||
'ha' => 100, // 公顷
|
||
'mu' => 1500, // 亩
|
||
'm2' => 1000000, // 平方米
|
||
'dm2' => 100000000, // 平方分米
|
||
'cm2' => 10000000000, // 平方厘米
|
||
'mm2' => 1000000000000, // 平方毫米
|
||
'sqmi' => 0.386102, // 平方英里
|
||
'acre' => 247.105381, // 英亩
|
||
'sqrd' => 39536.8670851, // 平方竿
|
||
'sqyd' => 1195990.046301, // 平方码
|
||
'sqft' => 10763910.41671, // 平方英尺
|
||
'sqin' => 1550003100.0062 // 平方英寸
|
||
];
|
||
|
||
// 检查输入的单位是否合法
|
||
if (!array_key_exists($unit, $conversion)) {
|
||
return false;
|
||
}
|
||
|
||
$results = [];
|
||
|
||
// 遍历每一个单位并进行换算
|
||
foreach ($conversion as $key => $factor) {
|
||
$result = $value * $factor;
|
||
$results[$key] = $result;
|
||
}
|
||
|
||
return $results;
|
||
}
|
||
// 体积单位换算
|
||
function convertVolume($value, $unit) {
|
||
// 定义单位之间的换算关系
|
||
$conversionTable = [
|
||
// 公制单位
|
||
'm3' => 1, //立方米(m3)
|
||
'hl' => 0.1, // 公石(hl)
|
||
'dal' => 0.01, // 十升(dal)
|
||
'dm3' => 0.001, // 立方分米(dm3)=升(l)
|
||
'dl' => 0.0001, // 分升(dl)
|
||
'cl' => 0.00001, // 厘升(cl)
|
||
'cm3' => 0.000001, // 立方厘米(cm3)=毫升(ml)
|
||
'mm3' => 0.000000001, // 立方毫米(mm3)
|
||
// 美制干量
|
||
'tong' => 0.1156281985, // 捅
|
||
'bu' => 0.03523907, // 蒲式耳
|
||
'pk' => 0.0088097678571429, // 配克
|
||
'qt' => 0.00110122094271, // 夸脱
|
||
'pt' => 0.000550610471, // 品脱
|
||
// 英制液量和干量
|
||
'tongs' => 0.163659239925, // 捅
|
||
'bus' => 0.036368719997, // 蒲式耳
|
||
'bal' => 0.00454609, // 加仑
|
||
'pts' => 0.00056826125, // 品脱(pt)
|
||
'floz' => 0.0000284130625, // 液体盎司
|
||
// 公制烹调制式
|
||
'tablespoon' => 0.000015, // 大汤匙
|
||
'teaspoon' => 0.000005, // 调羹
|
||
// 美制烹调制式
|
||
'tbs' => 0.00001478676, // 汤匙
|
||
'tsp' => 0.000004928922, // 茶匙
|
||
'flozs' => 0.000236588237, // 杯
|
||
// 美制液量
|
||
'tongss' => 0.158987294939, // 桶[42加仑]
|
||
'gal' => 0.00378541, // 加仑(gal)
|
||
'qts' => 0.00094635295, // 夸脱(qt)
|
||
'ptss' => 0.000473176475, // 品脱(pt)
|
||
'gi' => 0.00011829411825, // 及耳(gi)
|
||
'flozss' => 0.00002957353, // 液量盎司(fl oz)
|
||
'fldr' => 0.000003696691, // 液体打兰
|
||
'min' => 0.0000000004813399993896500, // 量滴(min)
|
||
// 美英同制体积计量
|
||
'acrefoot' => 1233.4818375, // 亩英尺
|
||
'cubicyard' => 0.764554858, // 立方码
|
||
'cubicfoot' => 0.028316846592, // 立方英尺
|
||
'cubicinch' => 0.000016387064, // 立方英寸
|
||
];
|
||
|
||
// 检查输入单位是否支持
|
||
if (!isset($conversionTable[$unit])) {
|
||
return false;
|
||
}
|
||
|
||
$results = [];
|
||
|
||
// 遍历所有单位进行换算
|
||
foreach ($conversionTable as $targetUnit => $conversionFactor) {
|
||
$result = $value * $conversionTable[$unit] / $conversionFactor;
|
||
$results[$targetUnit] = $result;
|
||
}
|
||
|
||
return $results;
|
||
}
|
||
// 压力单位换算
|
||
function convertPressure($value, $fromUnit)
|
||
{
|
||
// 建立单位间的换算因子数组
|
||
$conversionFactors = [
|
||
'bar' => 1,
|
||
'kpa' => 100,
|
||
'hpa' => 1000,
|
||
'mbar' => 1000,
|
||
'pa' => 100000,
|
||
'atm' => 0.986923,
|
||
'mmhg' => 750.06168,
|
||
'lbfft2' => 2088.5435,
|
||
'lbfin2' => 14.50377,
|
||
'inhg' => 29.529988,
|
||
'kgfcm2' => 1.0197162,
|
||
'kgfm2' => 10197.162,
|
||
'mmh2O' => 10197.2
|
||
];
|
||
|
||
// 检查输入单位是否存在
|
||
if (!array_key_exists($fromUnit, $conversionFactors)) {
|
||
return false;
|
||
}
|
||
|
||
$convertedValues = [];
|
||
|
||
// 遍历转换因子数组进行单位换算
|
||
foreach ($conversionFactors as $unit => $factor) {
|
||
$convertedValue = $value * ($factor / $conversionFactors[$fromUnit]);
|
||
$convertedValues[$unit] = $convertedValue;
|
||
}
|
||
|
||
return $convertedValues;
|
||
}
|
||
// 油耗计算
|
||
function calculateFuelConsumption($oilPrice, $moneySpent, $distance) {
|
||
// 计算总油耗量(升)
|
||
$totalFuel = $moneySpent / $oilPrice;
|
||
|
||
// 计算百公里油耗(升/公里),四舍五入保留一位小数
|
||
$fuelConsumptionPer100km = round(($totalFuel / $distance) * 100, 2);
|
||
|
||
// 计算每公里油耗(元/公里),四舍五入保留一位小数
|
||
$fuelCostPerKm = round($moneySpent / $distance, 2);
|
||
|
||
// 返回结果数组
|
||
$result = array(
|
||
'fuelConsumptionPer100km' => $fuelConsumptionPer100km,
|
||
'fuelCostPerKm' => $fuelCostPerKm
|
||
);
|
||
|
||
return $result;
|
||
}
|
||
// 房贷计算器
|
||
function calculateLoan($principal, $loanTerm, $repaymentMethod, $firstRepaymentMonth, $interestMode, $lprRate, $bpRate, $interestDiscount) {
|
||
// 将百分比的 LPR 利率转换为小数形式
|
||
$lprRate = $lprRate / 100;
|
||
|
||
// 根据利率模式计算实际利率
|
||
if ($interestMode == 'LPR+BP') {
|
||
// 计算 LPR+BP 模式下的基准利率
|
||
$baseInterestRate = $lprRate + $bpRate;
|
||
|
||
// 计算带入利率折扣后的实际利率
|
||
$actualInterestRate = $baseInterestRate * $interestDiscount;
|
||
} else {
|
||
// 固定利率模式下使用 LPR+BP 中的基本利率
|
||
$baseInterestRate = $lprRate + $bpRate;
|
||
|
||
// 固定利率模式下不考虑利率折扣
|
||
$actualInterestRate = $baseInterestRate;
|
||
}
|
||
|
||
// 将年利率转换为月利率
|
||
$monthlyInterestRate = $actualInterestRate / 12;
|
||
|
||
// 初始化还款明细数组
|
||
$repaymentDetails = array();
|
||
|
||
// 计算每月还款额
|
||
if ($repaymentMethod == '等额本金') {
|
||
// 等额本金方式下,每月还款额固定
|
||
$monthlyPrincipalPayment = $principal / $loanTerm;
|
||
$monthlyPayment = $monthlyPrincipalPayment + $principal * $monthlyInterestRate;
|
||
} else {
|
||
// 等额本息方式下,使用等额本息公式计算每月还款额
|
||
$monthlyPayment = ($principal * $monthlyInterestRate * pow(1 + $monthlyInterestRate, $loanTerm)) / (pow(1 + $monthlyInterestRate, $loanTerm) - 1);
|
||
$monthlyPrincipalPayment = $monthlyPayment - $principal * $monthlyInterestRate;
|
||
}
|
||
|
||
// 计算总还款额、总利息和剩余本金
|
||
$totalPayment = 0;
|
||
$totalInterest = 0;
|
||
$remainingPrincipal = $principal;
|
||
|
||
// 循环计算还款明细
|
||
for ($i = 1; $i <= $loanTerm; $i++) {
|
||
// 计算每月还息额
|
||
$interestPayment = $remainingPrincipal * $monthlyInterestRate;
|
||
|
||
// 计算每月还本金额
|
||
$principalPayment = $monthlyPrincipalPayment;
|
||
|
||
// 更新剩余本金
|
||
$remainingPrincipal -= $principalPayment;
|
||
|
||
// 构建还款明细数组
|
||
$repaymentDetails[] = array(
|
||
'期数' => $i,
|
||
'月份' => date('Y年m月', strtotime($firstRepaymentMonth . ' +' . ($i - 1) . ' month')),
|
||
'每月总还款(元)' => $monthlyPayment,
|
||
'每月还息(元)' => $interestPayment,
|
||
'每月还本金(元)' => $principalPayment,
|
||
'剩余本金(元)' => $remainingPrincipal
|
||
);
|
||
|
||
// 累加总还款额和总利息
|
||
$totalPayment += $monthlyPayment;
|
||
$totalInterest += $interestPayment;
|
||
}
|
||
|
||
// 返回计算结果
|
||
return array(
|
||
'总利息' => $totalInterest,
|
||
'每月总还款(月供)' => $monthlyPayment,
|
||
'还款明细数组' => $repaymentDetails
|
||
);
|
||
}
|
||
// BIM计算器
|
||
function calculateAndClassifyBMI($weight, $height) {
|
||
// 转换身高单位为米
|
||
$height = $height / 100;
|
||
|
||
// 计算 BMI
|
||
$bmi = $weight / ($height * $height);
|
||
if(strpos($bmi, '.') !== false){
|
||
// 如果有小数点,则四舍五入保留一位小数
|
||
$bmi = round($bmi, 1);
|
||
}
|
||
|
||
// 计算理想体重
|
||
$idealWeight = $height * $height * 21.7;
|
||
if (strpos($idealWeight, '.') !== false) {
|
||
// 如果有小数点,则四舍五入保留一位小数
|
||
$idealWeight = round($idealWeight, 1);
|
||
}
|
||
// 分类 BMI
|
||
if($bmi < 15){
|
||
$classification = "您太瘦,应去做个体检,增加营养。";
|
||
} else if ($bmi >= 15 && $bmi <= 18.4) {
|
||
$classification = "您过度苗条,应增加营养和锻炼。";
|
||
} elseif ($bmi >= 18.4 && $bmi < 22) {
|
||
$classification = "恭喜!!您是标准身材,注意保持。";
|
||
} elseif ($bmi >= 22 && $bmi <= 25) {
|
||
$classification = "您是健康体重,但已不苗条,小心。";
|
||
} elseif ($bmi >= 25 && $bmi < 30) {
|
||
$classification = "您超重了,应该立即减肥!";
|
||
} elseif ($bmi >= 30 && $bmi <= 40) {
|
||
$classification = "您很胖,减肥已是您的头等大事!";
|
||
} else if($bmi > 40){
|
||
$classification = "您非常胖,肥胖将危及您的健康!";
|
||
}
|
||
|
||
return [
|
||
'bmi' => $bmi, // bim指数
|
||
'suggest' => $classification,//建议
|
||
'idealWeight' => $idealWeight // 理想体重
|
||
];
|
||
}
|
||
// 去掉字符串中的html
|
||
function stripHtml($content){
|
||
$content = strip_tags($content);
|
||
$content = str_replace("\r\n", '', $content);
|
||
$content = str_replace("\t", '', $content);
|
||
$content = str_replace("\r", '', $content);
|
||
$content = str_replace("\n", '', $content);
|
||
$content = str_replace(" ", '', $content);
|
||
$content = html_entity_decode($content); // 将 HTML 实体转换为相应的字符
|
||
$content = preg_replace('/\s+/u', '', $content); // 去除所有空白字符
|
||
return trim($content);
|
||
}
|
||
// 匹配符号分割为数组
|
||
function tags($str){
|
||
$separator = ',、,-_|'; // 自定义的分隔符,包含逗号和顿号
|
||
$data = preg_split("/[" . preg_quote($separator) . "]/u", $str);
|
||
return $data;
|
||
}
|
||
// 百度主动推送
|
||
function baidupush($url){
|
||
$urls = [Request::instance()->domain().$url];
|
||
$api = 'http://data.zz.baidu.com/urls?site='.Request::instance()->domain().'&token='.Config::get('site.baidutoken');
|
||
$ch = curl_init();
|
||
$options = array(
|
||
CURLOPT_URL => $api,
|
||
CURLOPT_POST => true,
|
||
CURLOPT_RETURNTRANSFER => true,
|
||
CURLOPT_POSTFIELDS => implode("\n", $urls),
|
||
CURLOPT_HTTPHEADER => array('Content-Type: text/plain'),
|
||
);
|
||
curl_setopt_array($ch, $options);
|
||
$result = curl_exec($ch);
|
||
return $result;
|
||
}
|
||
// 必应推送
|
||
function biyingpush($url) {
|
||
$ch = curl_init();
|
||
curl_setopt($ch, CURLOPT_URL, "https://ssl.bing.com//webmaster/api.svc/json/SubmitUrlbatch?apikey=".Config::get('site.biyingtoken'));
|
||
curl_setopt($ch, CURLOPT_POST, 1);
|
||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
|
||
'siteUrl' => Request::instance()->domain(),
|
||
'urlList' => [Request::instance()->domain().$url]
|
||
]));
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||
'Host: ssl.bing.com',
|
||
'Content-Type: application/json; charset=utf-8'
|
||
]);
|
||
$response = curl_exec($ch);
|
||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||
curl_close($ch);
|
||
if ($http_code == 200 && json_decode($response)->d == null) {
|
||
return "推送成功";
|
||
foreach ($url_list as $url) {
|
||
return $url;
|
||
}
|
||
} else {
|
||
return "推送失败:推送配额不足";
|
||
}
|
||
}
|
||
// 神马推送
|
||
function shenmapush($url)
|
||
{
|
||
$urls = [Request::instance()->domain().$url];
|
||
$api = 'https://data.zhanzhang.sm.cn/push?site='.Request::instance()->host().'&user_name='.Config::get('site.shenma_user').'&resource_name=mip_add&token='.Config::get('site.authkey');
|
||
$ch = curl_init();
|
||
$options = array(
|
||
CURLOPT_URL => $api,
|
||
CURLOPT_POST => true,
|
||
CURLOPT_RETURNTRANSFER => true,
|
||
CURLOPT_POSTFIELDS => implode("\n", $urls),
|
||
CURLOPT_HTTPHEADER => array('Content-Type: text/plain'),
|
||
);
|
||
curl_setopt_array($ch, $options);
|
||
$result = json_decode(curl_exec($ch));
|
||
if(empty($result->returnCode)){
|
||
return '推送失败';exit();
|
||
}
|
||
if($result->returnCode == 200){
|
||
return '推送成功';exit();
|
||
}
|
||
if($result->returnCode == 201){
|
||
return 'token不合法';exit();
|
||
}
|
||
if($result->returnCode == 202){
|
||
return '当日流量已用完';exit();
|
||
}
|
||
if($result->returnCode == 400){
|
||
return '请求参数有误';exit();
|
||
}
|
||
if($result->returnCode == 500){
|
||
return '服务器内部错误';exit();
|
||
}
|
||
}
|
||
// 截取指定字符串
|
||
function cut_str($str,$length){
|
||
return mb_substr($str,0,$length,'UTF-8').'...';
|
||
}
|
||
// 蜘蛛访问记录
|
||
function Get_Spider()
|
||
{
|
||
$bot = '';
|
||
$request = Request::instance();
|
||
$userAgent = strtolower($request->header('user-agent'));
|
||
$ip = $request->ip();
|
||
if (stripos($userAgent,'Baiduspider') !== false) {
|
||
$bot = '百度';
|
||
} elseif (stripos($userAgent,'Sogou') !== false) {
|
||
$bot = '搜狗';
|
||
} elseif (stripos($userAgent,'bingbot') !== false) {
|
||
$bot = '必应';
|
||
}elseif (stripos($userAgent,'360Spider') !== false) {
|
||
$bot = '360';
|
||
}elseif (stripos($userAgent,'Bytespider') !== false) {
|
||
$bot = '头条';
|
||
}elseif(stripos($userAgent,'YisouSpider') !== false){
|
||
$bot = '神马';
|
||
}elseif(stripos($userAgent,'Googlebot') !== false){
|
||
$bot = '谷歌';
|
||
}elseif(stripos($userAgent,'Amazonbot') !== false){
|
||
$bot = '亚马逊';
|
||
}
|
||
// 如果是蜘蛛就存入数据库
|
||
if (!empty($bot)) {
|
||
Db::name('spiders')->insert(['name' => $bot,'ip' => $ip,'ua' => $userAgent,'createtime' => time()]);
|
||
}
|
||
}
|
||
// 多久之前
|
||
function formatTime($timestamp) {
|
||
$currentTime = time();
|
||
$timeDiff = $currentTime - $timestamp;
|
||
|
||
if ($timeDiff < 60) {
|
||
return '刚刚';
|
||
} elseif ($timeDiff < 3600) {
|
||
$minutes = floor($timeDiff / 60);
|
||
return $minutes . '分钟之前';
|
||
} elseif ($timeDiff < 86400) {
|
||
$hours = floor($timeDiff / 3600);
|
||
return $hours . '小时之前';
|
||
} elseif ($timeDiff < 2592000) {
|
||
$days = floor($timeDiff / 86400);
|
||
return $days . '天之前';
|
||
} elseif ($timeDiff < 31536000) {
|
||
$months = floor($timeDiff / 2592000);
|
||
return $months . '个月之前';
|
||
} else {
|
||
return date('Y-m-d', $timestamp);
|
||
}
|
||
}
|
||
// 截取出域名
|
||
function urls($url)
|
||
{
|
||
$parsedUrl = parse_url($url);
|
||
return $parsedUrl['host'];
|
||
}
|
||
// 字符串长度
|
||
function strlength($str){
|
||
$strs = mb_strlen($str,'utf8');
|
||
return $strs;
|
||
}
|
||
function getDateArray($start, $end)
|
||
{
|
||
$dateArray = [];
|
||
|
||
for ($date = $start; $date <= $end; $date = strtotime("+1 day", $date)) {
|
||
$day = date("j", $date);
|
||
$dateArray[] = $day;
|
||
}
|
||
|
||
return $dateArray;
|
||
}
|
||
function getBrowserOs()
|
||
{
|
||
$flag = $_SERVER['HTTP_USER_AGENT'];
|
||
if (preg_match('/Windows[\d\. \w]*/', $flag, $match)) {
|
||
$sys = $match[0];
|
||
} else {
|
||
$sys = 'Unknown';
|
||
}
|
||
// 检查操作系统
|
||
if (preg_match('/Chrome\/[\d\.\w]*/', $flag, $match)) {
|
||
// 检查Chrome
|
||
$browser = $match[0];
|
||
} elseif (preg_match('/Safari\/[\d\.\w]*/', $flag, $match)) {
|
||
// 检查Safari
|
||
$browser = $match[0];
|
||
} elseif (preg_match('/MSIE [\d\.\w]*/', $flag, $match)) {
|
||
// IE
|
||
$browser = $match[0];
|
||
} elseif (preg_match('/Opera\/[\d\.\w]*/', $flag, $match)) {
|
||
// opera
|
||
$browser = $match[0];
|
||
} elseif (preg_match('/Firefox\/[\d\.\w]*/', $flag, $match)) {
|
||
// Firefox
|
||
$browser = $match[0];
|
||
} elseif (preg_match('/OmniWeb\/(v*)([^\s|;]+)/i', $flag, $match)) {
|
||
//OmniWeb
|
||
$browser = $match[2];
|
||
} elseif (preg_match('/Netscape([\d]*)\/([^\s]+)/i', $flag, $match)) {
|
||
//Netscape
|
||
$browser = $match[2];
|
||
} elseif (preg_match('/Lynx\/([^\s]+)/i', $flag, $match)) {
|
||
//Lynx
|
||
$browser = $match[1];
|
||
} elseif (preg_match('/360SE/i', $flag, $match)) {
|
||
//360SE
|
||
$browser = '360安全浏览器';
|
||
} elseif (preg_match('/SE 2.x/i', $flag, $match)) {
|
||
//搜狗
|
||
$browser = '搜狗浏览器';
|
||
} else {
|
||
$browser = 'unkown';
|
||
}
|
||
return [$sys, $browser];
|
||
}
|
||
function getip($type = 0,$adv = false) {
|
||
$type = $type ? 1 : 0;
|
||
static $ip = NULL;
|
||
if ($ip !== NULL) return $ip[$type];
|
||
if($adv){
|
||
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||
$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
||
$pos = array_search('unknown',$arr);
|
||
if(false !== $pos) unset($arr[$pos]);
|
||
$ip = trim($arr[0]);
|
||
}elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
|
||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||
}elseif (isset($_SERVER['REMOTE_ADDR'])) {
|
||
$ip = $_SERVER['REMOTE_ADDR'];
|
||
}
|
||
}elseif (isset($_SERVER['REMOTE_ADDR'])) {
|
||
$ip = $_SERVER['REMOTE_ADDR'];
|
||
}
|
||
// IP地址合法验证
|
||
$long = sprintf("%u",ip2long($ip));
|
||
$ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
|
||
return $ip[$type];
|
||
}
|
||
// 字符串编码转换
|
||
function strToUTF8($strText)
|
||
{
|
||
$encode = mb_detect_encoding($strText, array('UTF-8', 'GB2312', 'GBK'));
|
||
if ($encode != "UTF-8") {
|
||
return @iconv($encode, 'UTF-8', $strText);
|
||
} else {
|
||
return $strText;
|
||
}
|
||
}
|
||
// 设置缓存类型
|
||
function setCache()
|
||
{
|
||
// 判断是否开启缓存
|
||
if(Config::get('site.cacheSwitch')){
|
||
$config = [
|
||
'type' => Config::get('site.cacheType'),
|
||
'expire' => Config::get('site.cacheInt')
|
||
];
|
||
return $config;
|
||
}else{
|
||
return false;
|
||
}
|
||
}
|
||
// 获取域名地址等信息
|
||
function Site_Request($type) {
|
||
$request = Request::instance();
|
||
if(empty($type) || !isset($type)){
|
||
return '参数错误';
|
||
}
|
||
if($type == 'domain'){
|
||
// 获取当前域名
|
||
return $request->domain();
|
||
}else if($type == 'file') {
|
||
// 获取当前入口文件
|
||
return $request->baseFile();
|
||
}else if($type == 'url') {
|
||
// 获取当前URL地址 不含域名
|
||
return $request->url();
|
||
}else if($type == 'url with domain'){
|
||
// 获取包含域名的完整URL地址
|
||
return $request->url(true);
|
||
}else if($type == 'url without query'){
|
||
// 获取当前URL地址 不含QUERY_STRING
|
||
return $request->baseUrl();
|
||
}else if($type == 'root'){
|
||
// 获取URL访问的ROOT地址
|
||
return $request->root();
|
||
}else if($type == 'root with domain'){
|
||
// 获取URL访问的ROOT地址
|
||
return $request->root(true);
|
||
}else if($type == 'pathinfo'){
|
||
// 获取URL地址中的PATH_INFO信息
|
||
return $request->pathinfo();
|
||
}else if($type == 'ext'){
|
||
// 获取URL地址中的后缀信息
|
||
return $request->ext();
|
||
}
|
||
} |