232 lines
5.9 KiB
PHP
232 lines
5.9 KiB
PHP
<?php
|
||
// 应用公共文件
|
||
use app\service\DictionaryService;
|
||
use app\service\file\FilesystemService;
|
||
use Hashids\Hashids;
|
||
use think\Collection;
|
||
use think\facade\Event;
|
||
use think\Model;
|
||
|
||
|
||
/**
|
||
* @return FilesystemService
|
||
*/
|
||
function filesystem(): FilesystemService
|
||
{
|
||
return app()->filesystem;
|
||
}
|
||
|
||
/**
|
||
* 写入日志
|
||
* @param array|string $event
|
||
* @param string $message
|
||
* @param mixed|null $data
|
||
* @return void
|
||
*/
|
||
function security_log_record(array|string $event, string $message, mixed $data = null): void
|
||
{
|
||
if (is_string($event)) {
|
||
$event = explode('.', $event);
|
||
}
|
||
if ($data instanceof Model) {
|
||
$data = $data->toArray();
|
||
}
|
||
if ($data instanceof Collection) {
|
||
$data = $data->toArray();
|
||
}
|
||
|
||
Event::trigger('sys:securityLogRecord', [$event, $message, $data]);
|
||
}
|
||
|
||
|
||
/**
|
||
* 获取字典内容
|
||
* @param string $name
|
||
* @param $default
|
||
* @return mixed
|
||
*/
|
||
function dict_get(string $name, $default = null): mixed
|
||
{
|
||
return dict()->get($name, $default);
|
||
}
|
||
|
||
/**
|
||
* 获取字典服务
|
||
* @return DictionaryService
|
||
*/
|
||
function dict(): DictionaryService
|
||
{
|
||
return app()->dict;
|
||
}
|
||
|
||
/**
|
||
* 将扁平数组列表转换为树形结构
|
||
* @param array $items 原始数组
|
||
* @param string $idKey ID字段名
|
||
* @param string $parentKey 父ID字段名
|
||
* @param string $childrenKey 子节点字段名
|
||
* @return array 树形结构
|
||
*/
|
||
function list_build_tree(array $items, string $idKey = 'id', string $parentKey = 'pid', string $childrenKey = 'children'): array
|
||
{
|
||
// 创建ID映射和结果树
|
||
$tree = [];
|
||
$map = [];
|
||
|
||
// 创建ID到数组元素的引用映射
|
||
foreach ($items as &$item) {
|
||
$map[$item[$idKey]] = &$item;
|
||
$item[$childrenKey] = []; // 初始化children
|
||
}
|
||
|
||
// 构建树结构
|
||
foreach ($items as &$item) {
|
||
$parentId = $item[$parentKey];
|
||
|
||
if (isset($map[$parentId])) {
|
||
// 当前项有父节点,添加到父节点的children
|
||
$map[$parentId][$childrenKey][] = &$item;
|
||
} else {
|
||
// 当前项是根节点,添加到树
|
||
$tree[] = &$item;
|
||
}
|
||
}
|
||
|
||
// 清理引用
|
||
unset($item);
|
||
|
||
return $tree;
|
||
}
|
||
|
||
|
||
/**
|
||
* @param int $minHashLength
|
||
* @return Hashids
|
||
*/
|
||
function hashids(int $minHashLength = 6): Hashids
|
||
{
|
||
$salt = (string)config('app.default_salt', '');
|
||
return new Hashids($salt, $minHashLength);
|
||
}
|
||
|
||
function snowflake_id(int $machineId = null): int
|
||
{
|
||
// 时间戳 42字节
|
||
$time = floor(microtime(true) * 1000);
|
||
// 当前时间 与 开始时间 差值
|
||
$time -= 1641862815726;
|
||
$base = decbin(1099511627775 + $time);
|
||
if ($machineId) {
|
||
$machineId = str_pad(decbin($machineId), 10, '0', STR_PAD_LEFT);
|
||
}
|
||
$random = str_pad(decbin(mt_rand(0, 4095)), 12, '0', STR_PAD_LEFT);
|
||
return bindec($base . $machineId . $random);
|
||
}
|
||
|
||
function guid($namespace = ''): string
|
||
{
|
||
|
||
$uid = uniqid("", true);
|
||
$data = $namespace;
|
||
$data .= $_SERVER['REQUEST_TIME'] ?? '';
|
||
$data .= $_SERVER['HTTP_USER_AGENT'] ?? '';
|
||
$data .= $_SERVER['LOCAL_ADDR'] ?? '';
|
||
$data .= $_SERVER['LOCAL_PORT'] ?? '';
|
||
$data .= $_SERVER['REMOTE_ADDR'] ?? '';
|
||
$data .= $_SERVER['REMOTE_PORT'] ?? '';
|
||
$hash = strtoupper(hash('ripemd128', $uid . md5($data)));
|
||
return
|
||
substr($hash, 0, 8) .
|
||
'-' .
|
||
substr($hash, 8, 4) .
|
||
'-' .
|
||
substr($hash, 12, 4) .
|
||
'-' .
|
||
substr($hash, 16, 4) .
|
||
'-' .
|
||
substr($hash, 20, 12);
|
||
}
|
||
|
||
function unique_str(): string
|
||
{
|
||
return md5(uniqid());
|
||
}
|
||
|
||
function get_agent_browser($userAgent = ''): string
|
||
{
|
||
if (str_contains($userAgent, 'MicroMessenger')) {
|
||
return 'Wechat';
|
||
} elseif (str_contains($userAgent, 'QQBrowser')) {
|
||
return 'QQ';
|
||
} elseif (str_contains($userAgent, 'MSIE') || str_contains($userAgent, 'Trident/7.0;') || str_contains($userAgent, 'rv:11.0')) {
|
||
return 'Explorer';
|
||
} elseif (str_contains($userAgent, 'Firefox')) {
|
||
return 'Firefox';
|
||
} elseif (str_contains($userAgent, 'Edg')) {
|
||
return 'Edge';
|
||
} elseif (str_contains($userAgent, 'Chrome')) {
|
||
return 'Chrome';
|
||
} elseif (str_contains($userAgent, 'Safari')) {
|
||
return 'Safari';
|
||
} elseif (str_contains($userAgent, 'Opera Mini') || str_contains($userAgent, 'Opera')) {
|
||
return 'Opera';
|
||
} else {
|
||
return 'Unknown';
|
||
}
|
||
}
|
||
|
||
function get_agent_device($agent = ''): string
|
||
{
|
||
if (stristr($agent, 'iPad')) {
|
||
$fb_fs = "iPad";
|
||
} else if (preg_match('/Android (([0-9_.]{1,3})+)/i', $agent, $version)) {
|
||
$fb_fs = "手机(Android " . $version[1] . ")";
|
||
} else if (stristr($agent, 'Linux')) {
|
||
$fb_fs = "电脑(Linux)";
|
||
} else if (preg_match('/iPhone OS (([0-9_.]{1,3})+)/i', $agent, $version)) {
|
||
$fb_fs = "手机(iPhone " . $version[1] . ")";
|
||
} else if (preg_match('/Mac OS X (([0-9_.]{1,5})+)/i', $agent, $version)) {
|
||
$fb_fs = "电脑(OS X " . $version[1] . ")";
|
||
} else if (preg_match('/unix/i', $agent)) {
|
||
$fb_fs = "Unix";
|
||
} else if (preg_match('/windows/i', $agent)) {
|
||
$fb_fs = "电脑(Windows)";
|
||
} else {
|
||
$fb_fs = "Unknown";
|
||
}
|
||
return $fb_fs;
|
||
}
|
||
|
||
function get_agent_os($userAgent): string
|
||
{
|
||
if (preg_match('/windows/i', $userAgent)) {
|
||
return 'Windows';
|
||
} elseif (preg_match('/iPhone/i', $userAgent)) {
|
||
return 'iOS';
|
||
} elseif (preg_match('/HarmonyOS/i', $userAgent)) {
|
||
return 'Android';
|
||
} elseif (preg_match('/Android/i', $userAgent)) {
|
||
return 'Android';
|
||
} elseif (preg_match('/mac/i', $userAgent)) {
|
||
return 'Mac';
|
||
} else {
|
||
return 'Unknown';
|
||
}
|
||
}
|
||
|
||
function agent_is_crawler($userAgent): bool
|
||
{
|
||
$crawlers = [
|
||
'googlebot', 'bingbot', 'slurp', 'baidu', 'duckduckbot',
|
||
'yandexbot', 'sogou', 'exabot', 'ia_archiver', 'facebot',
|
||
'facebookexternalhit'
|
||
];
|
||
|
||
foreach ($crawlers as $crawler) {
|
||
if (str_contains($userAgent, $crawler)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|