466 lines
12 KiB
PHP
466 lines
12 KiB
PHP
<?php
|
||
// 应用公共文件
|
||
use app\common\service\FileService;
|
||
use think\helper\Str;
|
||
use think\facade\Db;
|
||
/**
|
||
* @notes 生成密码加密密钥
|
||
* @param string $plaintext
|
||
* @param string $salt
|
||
* @return string
|
||
* @author 段誉
|
||
* @date 2021/12/28 18:24
|
||
*/
|
||
function create_password(string $plaintext, string $salt) : string
|
||
{
|
||
return md5($salt . md5($plaintext . $salt));
|
||
}
|
||
|
||
|
||
/**
|
||
* @notes 随机生成token值
|
||
* @param string $extra
|
||
* @return string
|
||
* @author 段誉
|
||
* @date 2021/12/28 18:24
|
||
*/
|
||
function create_token(string $extra = '') : string
|
||
{
|
||
$salt = env('project.unique_identification', 'likeadmin');
|
||
$encryptSalt = md5( $salt . uniqid());
|
||
return md5($salt . $extra . time() . $encryptSalt);
|
||
}
|
||
|
||
|
||
/**
|
||
* @notes 截取某字符字符串
|
||
* @param $str
|
||
* @param string $symbol
|
||
* @return string
|
||
* @author 段誉
|
||
* @date 2021/12/28 18:24
|
||
*/
|
||
function substr_symbol_behind($str, $symbol = '.') : string
|
||
{
|
||
$result = strripos($str, $symbol);
|
||
if ($result === false) {
|
||
return $str;
|
||
}
|
||
return substr($str, $result + 1);
|
||
}
|
||
|
||
|
||
/**
|
||
* @notes 对比php版本
|
||
* @param string $version
|
||
* @return bool
|
||
* @author 段誉
|
||
* @date 2021/12/28 18:27
|
||
*/
|
||
function compare_php(string $version) : bool
|
||
{
|
||
return version_compare(PHP_VERSION, $version) >= 0 ? true : false;
|
||
}
|
||
|
||
/**
|
||
* User: 青程信息科技 xc
|
||
* Desc: 返回是否有下一页
|
||
* @param $count 总记录数
|
||
* @param $page 当前页码
|
||
* @param $size 每页记录数
|
||
* @return int
|
||
*/
|
||
function is_more($count, $page, $size)
|
||
{
|
||
|
||
$more = 0;
|
||
|
||
$last_page = ceil($count / $size); //总页数、也是最后一页
|
||
|
||
if ($last_page && $last_page > $page) {
|
||
$more = 1;
|
||
}
|
||
return $more;
|
||
}
|
||
/**
|
||
* @notes 检查文件是否可写
|
||
* @param string $dir
|
||
* @return bool
|
||
* @author 段誉
|
||
* @date 2021/12/28 18:27
|
||
*/
|
||
function check_dir_write(string $dir = '') : bool
|
||
{
|
||
$route = root_path() . '/' . $dir;
|
||
return is_writable($route);
|
||
}
|
||
/**
|
||
* @notes 获取未来7天时间
|
||
* @param string $dir
|
||
* @return array|bool
|
||
* @author 胥聪
|
||
* @date 2025/10/20 17:01
|
||
*/
|
||
|
||
function getNext7Days($startDate = null) {
|
||
$dates = [];
|
||
$weekDays = ['日', '一', '二', '三', '四', '五', '六'];
|
||
|
||
$current = $startDate ? new DateTime($startDate) : new DateTime();
|
||
|
||
for ($i = 0; $i < 7; $i++) {
|
||
$date = clone $current;
|
||
$date->add(new DateInterval("P{$i}D"));
|
||
|
||
$dateStr = $date->format('m/d');
|
||
$weekDay = $weekDays[$date->format('w')];
|
||
$dateOnly = $date->format('Y-m-d'); // 获取完整日期
|
||
|
||
$dates[$i] = [
|
||
'display' => $dateStr . '周' . $weekDay,
|
||
'date' => $dateOnly, // 添加日期字段
|
||
'timestamp' => $date->getTimestamp(), // 添加当天0点的时间戳
|
||
];
|
||
|
||
$startHour = 8; // 早上8点
|
||
$endHour = 24; // 晚上12点(24点)
|
||
$time_slots = array();
|
||
|
||
// 生成该天从8点到24点的时间段
|
||
for ($hour = $startHour; $hour < $endHour; $hour++) {
|
||
$startTime = sprintf("%02d:00", $hour);
|
||
$timeString = $dateOnly . ' ' . $startTime; // 完整日期时间字符串
|
||
$slotTimestamp = strtotime($timeString); // 时间段的时间戳
|
||
|
||
$time_slots[] = [
|
||
'start_time' => $startTime,
|
||
'timestamp' => $slotTimestamp, // 添加时间段的时间戳
|
||
'datetime' => $timeString, // 添加完整的日期时间
|
||
'disabled' => 1
|
||
];
|
||
}
|
||
$dates[$i]['time_slots'] = $time_slots;
|
||
}
|
||
return $dates;
|
||
}
|
||
/**
|
||
* @notes 生产订单编号
|
||
* @param string $dir
|
||
* @return array|bool
|
||
* @author 胥聪
|
||
* @date 2025/10/20 17:01
|
||
*/
|
||
function createSn($table, $field, $prefix = '', $rand_suffix_length = 4, $pool = [])
|
||
{
|
||
$suffix = '';
|
||
for ($i = 0; $i < $rand_suffix_length; $i++) {
|
||
if (empty($pool)) {
|
||
$suffix .= rand(0, 9);
|
||
} else {
|
||
$suffix .= $pool[array_rand($pool)];
|
||
}
|
||
}
|
||
$sn = $prefix . date('YmdHis') . $suffix;
|
||
if (Db::name($table)->where($field, $sn)->find()) {
|
||
return createSn($table, $field, $prefix, $rand_suffix_length, $pool);
|
||
}
|
||
return $sn;
|
||
}
|
||
|
||
/**
|
||
* 根据经纬度计算两点之间的距离(公里)
|
||
* @param float $lat1 起点纬度
|
||
* @param float $lng1 起点经度
|
||
* @param float $lat2 终点纬度
|
||
* @param float $lng2 终点经度
|
||
* @param int $precision 保留小数位数
|
||
* @return float 距离(公里)
|
||
*/
|
||
function calculateDistanceKm($lat1, $lng1, $lat2, $lng2, $precision = 2)
|
||
{
|
||
// 将角度转换为弧度
|
||
$radLat1 = deg2rad($lat1);
|
||
$radLat2 = deg2rad($lat2);
|
||
$radLng1 = deg2rad($lng1);
|
||
$radLng2 = deg2rad($lng2);
|
||
|
||
// 差值
|
||
$latDiff = $radLat2 - $radLat1;
|
||
$lngDiff = $radLng2 - $radLng1;
|
||
|
||
// Haversine公式
|
||
$a = sin($latDiff / 2) * sin($latDiff / 2) +
|
||
cos($radLat1) * cos($radLat2) *
|
||
sin($lngDiff / 2) * sin($lngDiff / 2);
|
||
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
|
||
|
||
// 地球半径(公里)
|
||
$earthRadius = 6371;
|
||
$distance = $earthRadius * $c;
|
||
|
||
return round($distance, $precision);
|
||
}
|
||
|
||
/**
|
||
* 计算两点地理坐标之间的距离
|
||
* @param Decimal $longitude1 起点经度
|
||
* @param Decimal $latitude1 起点纬度
|
||
* @param Decimal $longitude2 终点经度
|
||
* @param Decimal $latitude2 终点纬度
|
||
* @param Int $unit 单位 1:米 2:公里(千米)
|
||
* @param Int $decimal 精度 保留小数位数
|
||
* @return Decimal
|
||
*/
|
||
function getDistance(float $longitude1, float $latitude1, float $longitude2, float $latitude2, $unit = 2, $decimal = 2)
|
||
{
|
||
|
||
$EARTH_RADIUS = 6370.996; // 地球半径系数
|
||
$PI = 3.1415926;
|
||
|
||
$radLat1 = $latitude1 * $PI / 180.0;
|
||
$radLat2 = $latitude2 * $PI / 180.0;
|
||
$radLng1 = $longitude1 * $PI / 180.0;
|
||
$radLng2 = $longitude2 * $PI / 180.0;
|
||
|
||
$a = $radLat1 - $radLat2;
|
||
$b = $radLng1 - $radLng2;
|
||
|
||
$distance = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));
|
||
$distance = $distance * $EARTH_RADIUS * 1000;
|
||
if ($unit == 2) {
|
||
$distance = $distance / 1000;
|
||
}
|
||
if ($unit == 1) {
|
||
$unit_msg = "m";
|
||
} else {
|
||
$unit_msg = "km";
|
||
}
|
||
return round($distance, $decimal) . $unit_msg;
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* 多级线性结构排序
|
||
* 转换前:
|
||
* [{"id":1,"pid":0,"name":"a"},{"id":2,"pid":0,"name":"b"},{"id":3,"pid":1,"name":"c"},
|
||
* {"id":4,"pid":2,"name":"d"},{"id":5,"pid":4,"name":"e"},{"id":6,"pid":5,"name":"f"},
|
||
* {"id":7,"pid":3,"name":"g"}]
|
||
* 转换后:
|
||
* [{"id":1,"pid":0,"name":"a","level":1},{"id":3,"pid":1,"name":"c","level":2},{"id":7,"pid":3,"name":"g","level":3},
|
||
* {"id":2,"pid":0,"name":"b","level":1},{"id":4,"pid":2,"name":"d","level":2},{"id":5,"pid":4,"name":"e","level":3},
|
||
* {"id":6,"pid":5,"name":"f","level":4}]
|
||
* @param array $data 线性结构数组
|
||
* @param string $symbol 名称前面加符号
|
||
* @param string $name 名称
|
||
* @param string $id_name 数组id名
|
||
* @param string $parent_id_name 数组祖先id名
|
||
* @param int $level 此值请勿给参数
|
||
* @param int $parent_id 此值请勿给参数
|
||
* @return array
|
||
*/
|
||
function linear_to_tree($data, $sub_key_name = 'sub', $id_name = 'id', $parent_id_name = 'pid', $parent_id = 0)
|
||
{
|
||
$tree = [];
|
||
foreach ($data as $row) {
|
||
if ($row[$parent_id_name] == $parent_id) {
|
||
$temp = $row;
|
||
$child = linear_to_tree($data, $sub_key_name, $id_name, $parent_id_name, $row[$id_name]);
|
||
if ($child) {
|
||
$temp[$sub_key_name] = $child;
|
||
}
|
||
$tree[] = $temp;
|
||
}
|
||
}
|
||
return $tree;
|
||
}
|
||
|
||
|
||
/**
|
||
* @notes 删除目标目录
|
||
* @param $path
|
||
* @param $delDir
|
||
* @return bool|void
|
||
* @author 段誉
|
||
* @date 2022/4/8 16:30
|
||
*/
|
||
function del_target_dir($path, $delDir)
|
||
{
|
||
//没找到,不处理
|
||
if (!file_exists($path)) {
|
||
return false;
|
||
}
|
||
|
||
//打开目录句柄
|
||
$handle = opendir($path);
|
||
if ($handle) {
|
||
while (false !== ($item = readdir($handle))) {
|
||
if ($item != "." && $item != "..") {
|
||
if (is_dir("$path/$item")) {
|
||
del_target_dir("$path/$item", $delDir);
|
||
} else {
|
||
unlink("$path/$item");
|
||
}
|
||
}
|
||
}
|
||
closedir($handle);
|
||
if ($delDir) {
|
||
return rmdir($path);
|
||
}
|
||
} else {
|
||
if (file_exists($path)) {
|
||
return unlink($path);
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @notes 下载文件
|
||
* @param $url
|
||
* @param $saveDir
|
||
* @param $fileName
|
||
* @return string
|
||
* @author 段誉
|
||
* @date 2022/9/16 9:53
|
||
*/
|
||
function download_file($url, $saveDir, $fileName)
|
||
{
|
||
if (!file_exists($saveDir)) {
|
||
mkdir($saveDir, 0775, true);
|
||
}
|
||
$fileSrc = $saveDir . $fileName;
|
||
file_exists($fileSrc) && unlink($fileSrc);
|
||
$ch = curl_init();
|
||
curl_setopt($ch, CURLOPT_URL, $url);
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
|
||
$file = curl_exec($ch);
|
||
curl_close($ch);
|
||
$resource = fopen($fileSrc, 'a');
|
||
fwrite($resource, $file);
|
||
fclose($resource);
|
||
if (filesize($fileSrc) == 0) {
|
||
unlink($fileSrc);
|
||
return '';
|
||
}
|
||
return $fileSrc;
|
||
}
|
||
|
||
|
||
/**
|
||
* @notes 去除内容图片域名
|
||
* @param $content
|
||
* @return array|string|string[]
|
||
* @author 段誉
|
||
* @date 2022/9/26 10:43
|
||
*/
|
||
function clear_file_domain($content)
|
||
{
|
||
$fileUrl = FileService::getFileUrl();
|
||
$pattern = '/<img[^>]*\bsrc=["\']'.preg_quote($fileUrl, '/').'([^"\']+)["\']/i';
|
||
return preg_replace($pattern, '<img src="$1"', $content);
|
||
}
|
||
|
||
/**
|
||
* @notes 设置内容图片域名
|
||
* @param $content
|
||
* @return array|string|string[]|null
|
||
* @author 段誉
|
||
* @date 2024/2/5 16:36
|
||
*/
|
||
function get_file_domain($content)
|
||
{
|
||
$fileUrl = FileService::getFileUrl();
|
||
$imgPreg = '/(<img .*?src=")(?!https?:\/\/)([^"]*)(".*?>)/is';
|
||
$videoPreg = '/(<video .*?src=")(?!https?:\/\/)([^"]*)(".*?>)/is';
|
||
$content = preg_replace($imgPreg, "\${1}$fileUrl\${2}\${3}", $content);
|
||
$content = preg_replace($videoPreg, "\${1}$fileUrl\${2}\${3}", $content);
|
||
return $content;
|
||
}
|
||
|
||
/**
|
||
* @notes uri小写
|
||
* @param $data
|
||
* @return array|string[]
|
||
* @author 段誉
|
||
* @date 2022/7/19 14:50
|
||
*/
|
||
function lower_uri($data)
|
||
{
|
||
if (!is_array($data)) {
|
||
$data = [$data];
|
||
}
|
||
return array_map(function ($item) {
|
||
return strtolower(Str::camel($item));
|
||
}, $data);
|
||
}
|
||
|
||
|
||
/**
|
||
* @notes 获取无前缀数据表名
|
||
* @param $tableName
|
||
* @return mixed|string
|
||
* @author 段誉
|
||
* @date 2022/12/12 15:23
|
||
*/
|
||
function get_no_prefix_table_name($tableName)
|
||
{
|
||
$tablePrefix = config('database.connections.mysql.prefix');
|
||
$prefixIndex = strpos($tableName, $tablePrefix);
|
||
if ($prefixIndex !== 0 || $prefixIndex === false) {
|
||
return $tableName;
|
||
}
|
||
$tableName = substr_replace($tableName, '', 0, strlen($tablePrefix));
|
||
return trim($tableName);
|
||
}
|
||
|
||
|
||
/**
|
||
* @notes 生成编码
|
||
* @param $table
|
||
* @param $field
|
||
* @param string $prefix
|
||
* @param int $randSuffixLength
|
||
* @param array $pool
|
||
* @return string
|
||
* @author 段誉
|
||
* @date 2023/2/23 11:35
|
||
*/
|
||
function generate_sn($table, $field, $prefix = '', $randSuffixLength = 4, $pool = []) : string
|
||
{
|
||
$suffix = '';
|
||
for ($i = 0; $i < $randSuffixLength; $i++) {
|
||
if (empty($pool)) {
|
||
$suffix .= rand(0, 9);
|
||
} else {
|
||
$suffix .= $pool[array_rand($pool)];
|
||
}
|
||
}
|
||
$sn = $prefix . date('YmdHis') . $suffix;
|
||
if (app()->make($table)->where($field, $sn)->find()) {
|
||
return generate_sn($table, $field, $prefix, $randSuffixLength, $pool);
|
||
}
|
||
return $sn;
|
||
}
|
||
|
||
|
||
/**
|
||
* @notes 格式化金额
|
||
* @param $float
|
||
* @return int|mixed|string
|
||
* @author 段誉
|
||
* @date 2023/2/24 11:20
|
||
*/
|
||
function format_amount($float)
|
||
{
|
||
if ($float == intval($float)) {
|
||
return intval($float);
|
||
} elseif ($float == sprintf('%.1f', $float)) {
|
||
return sprintf('%.1f', $float);
|
||
}
|
||
return $float;
|
||
}
|