601 lines
18 KiB
PHP
Executable File
601 lines
18 KiB
PHP
Executable File
<?php
|
|
use support\Env;
|
|
if (!function_exists('admin_path')) {
|
|
function admin_path(){
|
|
return '/app/admin';
|
|
}
|
|
}
|
|
if (!function_exists('cache')) {
|
|
/**
|
|
* 缓存管理
|
|
* @param string $name 缓存名称
|
|
* @param mixed $value 缓存值
|
|
* @param mixed $options 缓存参数
|
|
* @param string $tag 缓存标签
|
|
* @return mixed
|
|
*/
|
|
function cache(string $name = null, $value = '', $options = null, $tag = null)
|
|
{
|
|
if (is_null($name)) {
|
|
return '';
|
|
}
|
|
|
|
if ('' === $value) {
|
|
// 获取缓存
|
|
return str_starts_with($name, '?') ? \support\think\Cache::has(substr($name, 1)) : \support\think\Cache::get($name);
|
|
} elseif (is_null($value)) {
|
|
// 删除缓存
|
|
return \support\think\Cache::delete($name);
|
|
}
|
|
|
|
// 缓存数据
|
|
if (is_array($options)) {
|
|
$expire = $options['expire'] ?? null; //修复查询缓存无法设置过期时间
|
|
} else {
|
|
$expire = $options;
|
|
}
|
|
|
|
if (is_null($tag)) {
|
|
return \support\think\Cache::set($name, $value, $expire);
|
|
} else {
|
|
return \support\think\Cache::tag($tag)->set($name, $value, $expire);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!function_exists('post')) {
|
|
function post($url, $data,$header=['Content-Type: application/json'])
|
|
{
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_POST, 1);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
|
|
if($header){
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // 设置请求头
|
|
}
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
//curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
|
|
$response = curl_exec($ch);
|
|
curl_close($ch);
|
|
return $response;
|
|
}
|
|
}
|
|
|
|
if (!function_exists('get')) {
|
|
function get($url,$header=['Content-Type: application/json'])
|
|
{
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
if($header){
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // 设置请求头
|
|
}
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
$response = curl_exec($ch);
|
|
curl_close($ch);
|
|
return $response;
|
|
}
|
|
}
|
|
|
|
if (!function_exists('__')) {
|
|
function __(string $name = '', array $parameters = [], ?string $domain = null, ?string $locale = null)
|
|
{
|
|
// $locale = $locale ?: locale();
|
|
// if(!$domain){
|
|
// $request = Request();
|
|
// $request->app.','.$request->plugin.','.get_controller_name();
|
|
// $fn = '/resource/translations/'.$locale.'/'.($request->app ? $request->app .'/' : '').strtolower(get_controller_name());
|
|
|
|
// if($request->plugin){
|
|
// $fn = base_path('plugin').'/'.$request->plugin.$fn;
|
|
// }else{
|
|
// $fn = base_path($fn);
|
|
// }
|
|
// $domain = $fn;
|
|
// }
|
|
return trans($name, $parameters, $domain, $locale);
|
|
}
|
|
}
|
|
/**
|
|
* 跨域检测
|
|
*/
|
|
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 {
|
|
abort('跨域检测无效', 403);
|
|
}
|
|
|
|
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']}");
|
|
}
|
|
abort('', 200);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!function_exists('check_ip_allowed')) {
|
|
/**
|
|
* 检测IP是否允许
|
|
* @param string $ip IP地址
|
|
*/
|
|
function check_ip_allowed($ip = null)
|
|
{
|
|
$ip = is_null($ip) ? getRealIp() : $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 && in_array($ip, $forbiddenipArr)) {
|
|
abort('请求无权访问', 403);
|
|
}
|
|
}
|
|
}
|
|
if (!function_exists('Hook')) {
|
|
function Hook(?string $key = null, mixed $default = null)
|
|
{
|
|
//return \Webman\Event\Event::dispatch($key, $default);//不会自动处理错误
|
|
return \Webman\Event\Event::emit($key, $default);//会自动处理错误
|
|
}
|
|
}
|
|
|
|
if (!function_exists('addJob')) {
|
|
function addJob($data, $queue = 'Default', $delay = 0)
|
|
{
|
|
//$queue = 'Default';
|
|
if ($delay) {
|
|
// 投递延迟消息,消息会在60秒后处理
|
|
\Webman\RedisQueue\Redis::send($queue, $data, $delay);
|
|
} else {
|
|
// 投递消息
|
|
\Webman\RedisQueue\Redis::send($queue, $data);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!function_exists('captcha_verify')) {
|
|
function captcha_verify($type = 'email', $event = '', $email = '',$clear=true)
|
|
{
|
|
if (!$event) {
|
|
abort(__('Captcha event is incorrect'));
|
|
}
|
|
$cache_key = 'captcha_' . $event . '_' . $email;
|
|
$expires = 5 * 60; //5分钟
|
|
$code = Request()->post('code');
|
|
$list = cache($cache_key);
|
|
$list = $list ?: [];
|
|
if (!isset($list[$code])) {
|
|
abort(__('Captcha is incorrect'));
|
|
}
|
|
if ($list[$code] + $expires < time()) {
|
|
unset($list[$code]);
|
|
cache($cache_key, $list);
|
|
abort(__('Captcha has expired'));
|
|
}
|
|
if($clear){
|
|
unset($list[$code]);
|
|
if ($event && $email) {
|
|
cache($cache_key, null);
|
|
} else {
|
|
cache($cache_key, $list);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
if (!function_exists('cdnurl')) {
|
|
function cdnurl($path = '')
|
|
{
|
|
if(!$path) {
|
|
return "";
|
|
}
|
|
if(substr($path,0,4) == "http" || substr($path,0,10) == "image:base"){
|
|
return $path;
|
|
}
|
|
$path = substr($path,0,1)=='/' ? $path : '/'.$path;
|
|
return Config('site.cdnurl') . $path;
|
|
//return $path ? domain() . $path : $path;
|
|
}
|
|
}
|
|
if (!function_exists('abort')) {
|
|
function abort($msg = '', $code = 500)
|
|
{
|
|
throw new \support\exception\BusinessException($msg, $code);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('P')) {
|
|
function P()
|
|
{
|
|
$args = func_get_args();
|
|
echo '<pre>';
|
|
foreach($args as $arg){
|
|
print_r($arg);
|
|
print_r(PHP_EOL);
|
|
}
|
|
echo '</pre>';
|
|
}
|
|
}
|
|
|
|
if (!function_exists('cp')) {
|
|
function cp()
|
|
{
|
|
$args = func_get_args();
|
|
foreach($args as $arg){
|
|
print_r($arg);
|
|
print("\t");
|
|
}
|
|
echo "\n";
|
|
}
|
|
}
|
|
|
|
if (!function_exists('formatAmount')) {
|
|
function formatAmount($amount, $wei = 4)
|
|
{
|
|
if (!$amount) {
|
|
return 0;
|
|
}
|
|
return round($amount, $wei);
|
|
}
|
|
}
|
|
if (!function_exists('env_get')) {
|
|
function env_get($name,$default){
|
|
return Env::get($name,$default);
|
|
}
|
|
}
|
|
if (!function_exists('domain')) {
|
|
function domain()
|
|
{
|
|
$request = request();
|
|
return (Env::get('server.https')?'https':'http').'://'.($request ? $request->host() : Env::get('server.domain',''));
|
|
|
|
}
|
|
}
|
|
|
|
if (!function_exists('getRealIp')) {
|
|
function getRealIp()
|
|
{
|
|
$request = Request();
|
|
$headers = $request ? $request->header() : [];
|
|
$ip = $request ? $request->getRealIp() : '';
|
|
if (isset($headers['cf-connecting-ip'])) {
|
|
$ip = $headers['cf-connecting-ip'];
|
|
}
|
|
return $ip;
|
|
}
|
|
}
|
|
|
|
if (!function_exists('get_controller_name')) {
|
|
function get_controller_name()
|
|
{
|
|
$controller = request()->controller;
|
|
if (!$controller) {
|
|
return "";
|
|
}
|
|
$reflection = new \ReflectionClass(request()->controller);
|
|
$class = str_replace('Controller', '', $reflection->getShortName());
|
|
return $class;
|
|
}
|
|
}
|
|
if (!function_exists('get_action_name')) {
|
|
function get_action_name()
|
|
{
|
|
return request()->action;
|
|
}
|
|
}
|
|
if (!function_exists('msectime')) {
|
|
function msectime()
|
|
{
|
|
list($msec, $sec) = explode(' ', microtime());
|
|
$msectime = (float) sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
|
|
|
|
return $msectime;
|
|
}
|
|
}
|
|
if (!function_exists('cache_add')) {
|
|
function cache_add(string $key, int $value = 1, ?string $tag = null): void
|
|
{
|
|
static $tagMap = [
|
|
'user_recharge_total_' => 'recharge_total',
|
|
'user_income_total_' => 'income_total',
|
|
'user_consume_total_' => 'consume_total',
|
|
'team_user_total_' => 'team_user_total',
|
|
'team_direct_total_' => 'team_direct_total',
|
|
'team_vip_total_' => 'team_vip_total',
|
|
'team_recharge_total_' => 'team_recharge_total',
|
|
'team_withdrawl_total_' => 'team_withdrawl_total',
|
|
'team_income_total_' => 'team_income_total',
|
|
'team_consume_total_' => 'team_consume_total',
|
|
];
|
|
|
|
foreach ($tagMap as $prefix => $cacheTag) {
|
|
if (str_starts_with($key, $prefix)) {
|
|
$tag = $cacheTag;
|
|
break;
|
|
}
|
|
}
|
|
|
|
$old_value = cache_get($key);
|
|
cache($key, $old_value + $value, null, $tag);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('cache_get')) {
|
|
function cache_get(string $key, bool $force = false): mixed
|
|
{
|
|
static $queryMap = [
|
|
'team_user_total_' => ['table' => 'user_extend', 'field' => 'team_total'],
|
|
'team_direct_total_' => ['table' => 'user_extend', 'field' => 'direct_total'],
|
|
'team_vip_total_' => ['table' => 'user_extend', 'field' => 'vip_total'],
|
|
];
|
|
|
|
$ret = cache($key) ?: 0;
|
|
|
|
if (!$ret || $force) {
|
|
$matched = false;
|
|
|
|
foreach ($queryMap as $prefix => $config) {
|
|
if (str_starts_with($key, $prefix)) {
|
|
$user_id = substr($key, strlen($prefix));
|
|
$ret = \support\think\Db::name($config['table'])
|
|
->where('user_id', $user_id)
|
|
->value($config['field']);
|
|
$matched = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!$matched && str_starts_with($key, 'article_read_')) {
|
|
$parts = explode('_', substr($key, strlen('article_read_')));
|
|
if (count($parts) === 2) {
|
|
$ret = \support\think\Db::name('archives_read')
|
|
->where('source_id', $parts[0])
|
|
->where('user_id', $parts[1])
|
|
->value('value');
|
|
}
|
|
}
|
|
|
|
cache($key, $ret);
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
}
|
|
if (!function_exists('build_invite_code')) {
|
|
function build_invite_code($id = '')
|
|
{
|
|
if (empty($id)) {
|
|
return '';
|
|
}
|
|
|
|
// 使用一个固定的种子值来增加随机性
|
|
$seed = 0x7F4A8C3B;
|
|
|
|
// 将用户ID转换为数字并加入种子
|
|
$num = intval($id) + $seed;
|
|
|
|
// 使用一个固定的字符集(去掉容易混淆的字符)
|
|
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
|
|
$chars_len = strlen($chars);
|
|
|
|
$code = '';
|
|
// 生成8位邀请码
|
|
for ($i = 0; $i < 8; $i++) {
|
|
// 使用不同的数学运算来打乱数字
|
|
$num = ($num * 31 + $seed) % 0x7FFFFFFF;
|
|
// 确保每次取模的结果在字符集范围内
|
|
$index = ($num % $chars_len + $chars_len) % $chars_len;
|
|
$code .= $chars[$index];
|
|
}
|
|
|
|
return $code;
|
|
}
|
|
}
|
|
|
|
if (!function_exists('get_parent_id')) {
|
|
function get_parent_id($user_id)
|
|
{
|
|
if (!$user_id) {
|
|
return "";
|
|
}
|
|
$info = parent_info( $user_id);
|
|
return $info['id'];
|
|
}
|
|
}
|
|
if (!function_exists('parent_info')) {
|
|
function parent_info($user_id,$value=[])
|
|
{
|
|
if (!$user_id) {
|
|
return "";
|
|
}
|
|
if($value){
|
|
cache('user_parent_info_' . $user_id, $value);
|
|
return $value;
|
|
}
|
|
$info = cache('user_parent_info_' . $user_id);
|
|
if (!$info) {
|
|
$parent_id = \app\model\User::where('id', $user_id)
|
|
->value('parent_id');
|
|
$info = [['id'=>'','username'=>'']];
|
|
if($parent_id){
|
|
$info = \app\model\User::where('id',$parent_id)->column('id,username');
|
|
}
|
|
cache('user_parent_info_' . $user_id, $info[0]);
|
|
}
|
|
return $info;
|
|
}
|
|
}
|
|
|
|
if(!function_exists('datetime')){
|
|
function datetime($timestamp=0,$format='Y-m-d H:i:s'){
|
|
if(!$timestamp){return '';}
|
|
if(strpos($timestamp,'-')===false){
|
|
if(!$timestamp){return '';}
|
|
if($format == 'datetime'){
|
|
$format = 'Y-m-d H:i:s';
|
|
}
|
|
if($format == 'date'){
|
|
$format = 'Y-m-d';
|
|
}
|
|
if($format == 'time'){
|
|
$format = 'H:i:s';
|
|
}
|
|
return date($format,$timestamp);
|
|
}
|
|
return $timestamp;
|
|
}
|
|
}
|
|
if(!function_exists('log_alert')){
|
|
function log_alert($data='',$channel='default'){
|
|
if(!is_string($data)){
|
|
$data = json_encode($data);
|
|
}
|
|
// if(is_string($data) || is_numeric($data) || is_bool($data)){
|
|
// }else{
|
|
// $data = json_encode($data);
|
|
// }
|
|
\support\Log::channel($channel)->alert($data);
|
|
}
|
|
}
|
|
if(!function_exists('enum_dir')){
|
|
function enum_dir($path=''){
|
|
$list = [];
|
|
//$path = substr(0,1,$path) == '/' ? $path
|
|
foreach(glob($path) as $afile){
|
|
if(is_dir($afile)){
|
|
cp($afile);
|
|
//$list[] = enum_dir($afile);
|
|
} else {
|
|
$list[]=$afile;
|
|
//rename('./'.$afile,'./'.$name);
|
|
echo $afile,"\n";
|
|
}
|
|
}
|
|
return $list ;
|
|
}
|
|
}
|
|
|
|
if(!function_exists('get_user_rights')){
|
|
function get_user_rights($user_id):array{
|
|
$user_id = idDecode($user_id);
|
|
$key = 'user_rights_'.$user_id;
|
|
$result = cache($key);
|
|
if(!$result){
|
|
$result = \think\facade\Db::name('user_role')->alias('ur')
|
|
->join('user u','ur.id = u.role_id')
|
|
->where('u.id',$user_id)
|
|
->field('ur.name,ur.right')
|
|
->find();
|
|
$result['right'] = json_decode($result['right'],true);
|
|
cache($key,$result,86400);
|
|
}
|
|
return $result;
|
|
}
|
|
}
|
|
if(!function_exists('array_find')){
|
|
function array_find(array $array,callable $callbcak):mixed{
|
|
foreach ($array as $key => $value) {
|
|
if ($callbcak($value, $key)) {
|
|
return $value;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
if(!function_exists('__my__template_inputs')){
|
|
function __my__template_inputs(&$template, &$vars, &$app, &$plugin){
|
|
// cp('__after__template_inputs:');
|
|
// cp('template:'.$template);
|
|
// cp('app:'.$app);
|
|
// cp('plugin:'.$plugin);
|
|
$request = request();
|
|
if(!$template){
|
|
$baseViewPath = $plugin ? base_path() . "/plugin/$plugin/app" : app_path();
|
|
$viewPath = $app === '' ? "$baseViewPath/view/" : "$baseViewPath/$app/view/";
|
|
$template = strtolower($request->controller_name."/".$request->action_name);
|
|
}
|
|
if(count(explode('/',$template)) == 1){
|
|
$template = strtolower($request->controller_name."/".$template);
|
|
}
|
|
return [$template, $vars, $app, $plugin];
|
|
|
|
}
|
|
}
|
|
|
|
if(!function_exists('update_user_level')){
|
|
function update_user_level($user_id,$count=0){
|
|
$levels = [
|
|
0,
|
|
50,
|
|
100,
|
|
1000,
|
|
5000,
|
|
20000,
|
|
];
|
|
$level = 0;
|
|
foreach($levels as $k=>$v){
|
|
if($count>=$v){
|
|
$level= $k;
|
|
}else{
|
|
break;
|
|
}
|
|
}
|
|
\support\think\Db::name('user')->where('id',$user_id)->data(['level'=>$level])->save();
|
|
|
|
}}
|
|
|
|
if(!function_exists('build_user_team')){
|
|
function build_user_team($user){
|
|
// 插入自己的团队关系 (自己是自己的后代)
|
|
$teamData = [
|
|
[
|
|
'ancestor_id' => $user['id'],
|
|
'descendant_id' => $user['id'],
|
|
'depth' => 0,
|
|
'status' => 0,
|
|
]
|
|
];
|
|
// 2. 处理团队关系(如果有推荐人)
|
|
if ($user['parent_id']) {
|
|
|
|
parent_info( $user['id'],[
|
|
'id' => $user['parent_id'],
|
|
'username' => \support\think\Db::name('user')->where('id',$user['parent_id'])->value('username')
|
|
]);
|
|
// 获取推荐人所有的上级关系,生成新用户的团队关系
|
|
$ancestors = \support\think\Db::name('user_team')
|
|
->where('descendant_id', $user['parent_id'])
|
|
->select();
|
|
/** @var \app\model\UserTeam $ancestor */
|
|
// 插入新用户与祖先的关系
|
|
foreach ($ancestors as $ancestor) {
|
|
$teamData[] = [
|
|
'ancestor_id' => $ancestor['ancestor_id'],
|
|
'descendant_id' => $user['id'],
|
|
'depth' => $ancestor['depth'] + 1,
|
|
'status' => 1, // 默认状态为 0,表示无效
|
|
];
|
|
}
|
|
}
|
|
// 批量插入关系
|
|
try {
|
|
if($teamData){
|
|
\support\think\Db::name('user_team')->insertAll($teamData);
|
|
}
|
|
} catch (\Exception $e) {
|
|
cp($e->getMessage());
|
|
}
|
|
}
|
|
} |