first commit

This commit is contained in:
2026-01-25 18:18:09 +08:00
commit 509312e604
8136 changed files with 2349298 additions and 0 deletions

13
common/CommonHelper.php Normal file
View File

@ -0,0 +1,13 @@
<?php
namespace app\common;
class CommonHelper
{
public static function getYear(string $title)
{
preg_match('/([0-9]+)/', $title, $y);
return $y[1] ?? date('Y');
}
}

167
common/CurlApp.php Normal file
View File

@ -0,0 +1,167 @@
<?php
namespace app\common;
class CurlApp
{
private $ch = null;
private array $options = [];
private string $headerContentType = '';
private string $error = '';
const METHOD_POST = 'POST';
const METHOD_GET = 'GET';
const CONTENT_TYPE_JSON = 'Content-Type: application/json';
const CONTENT_TYPE_FORM_URLENCODED = 'Content-Type: application/x-www-form-urlencoded';
public function __construct()
{
$this->ch = curl_init();
$this->options[CURLOPT_CONNECTTIMEOUT] = 30;
$this->options[CURLOPT_TIMEOUT] = 30;
}
public function setUrl(string $url)
{
$this->options[CURLOPT_URL] = $url;
return $this;
}
public function setCookie(string $cookie)
{
$this->options[CURLOPT_COOKIE] = $cookie;
return $this;
}
public function setReturnTransfer(bool $isReturn = true)
{
$this->options[CURLOPT_RETURNTRANSFER] = $isReturn;
return $this;
}
public function setPostData($data)
{
$this->options[CURLOPT_POSTFIELDS] = $data;
if ($this->headerContentType === self::CONTENT_TYPE_FORM_URLENCODED) {
if (is_array($data)) {
$this->options[CURLOPT_POSTFIELDS] = http_build_query($data);
}
} elseif ($this->headerContentType === self::CONTENT_TYPE_JSON) {
if (is_array($data)) {
$this->options[CURLOPT_POSTFIELDS] = json_encode($data);
} else {
$this->options[CURLOPT_POSTFIELDS] = ($data);
}
}
return $this;
}
public function setHttpHeader(array $header = [])
{
foreach ($header as $key => $value) {
$this->options[CURLOPT_HTTPHEADER][$key] = $value;
}
return $this;
}
public function setProxy($ip, $port)
{
// 基本代理
$this->options[CURLOPT_PROXY] = "{$ip}:{$port}";
// 指定代理类型可选HTTP、SOCKS4、SOCKS5
$this->options[CURLOPT_PROXYTYPE] = CURLPROXY_HTTP;
}
public function setContentType($contentType)
{
$this->headerContentType = $contentType;
$this->options[CURLOPT_HTTPHEADER][] = $contentType;
return $this;
}
public function setMethod($method = 'GET')
{
$this->options[CURLOPT_POST] = !(strtolower($method) == 'get');
return $this;
}
public function execMulti($urls = []): array
{
$multiHandle = curl_multi_init();
$handles = [];
$responses = [];
foreach ($urls as $key => $url) {
$ch = curl_init();
$this->options[CURLOPT_CONNECTTIMEOUT] = 60;
$this->options[CURLOPT_TIMEOUT] = 60;
// 继承当前 CurlApp 的 options
$options = $this->options;
$options[CURLOPT_URL] = $url;
$options[CURLOPT_RETURNTRANSFER] = true;
curl_setopt_array($ch, $options);
curl_multi_add_handle($multiHandle, $ch);
$handles[$key] = $ch;
}
// 执行
$running = null;
do {
$status = curl_multi_exec($multiHandle, $running);
if ($running) {
curl_multi_select($multiHandle, 1);
}
} while ($running && $status === CURLM_OK);
// 收集结果
foreach ($handles as $key => $ch) {
$responses[$key] = curl_multi_getcontent($ch);
curl_multi_remove_handle($multiHandle, $ch);
curl_close($ch);
}
curl_multi_close($multiHandle);
return $responses;
}
public function exec()
{
$defaultOptions = [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYHOST => false,
];
foreach ($defaultOptions as $key => $val) {
if (!isset($this->options[$key])) {
$this->options[$key] = $val;
}
}
curl_setopt_array($this->ch, $this->options);
$resp = curl_exec($this->ch);
if (curl_errno($this->ch)) {
$this->error = curl_error($this->ch);
return false;
}
curl_close($this->ch);
return $resp;
}
public function getError()
{
return $this->error;
}
}

283
common/FileHelper.php Normal file
View File

@ -0,0 +1,283 @@
<?php
namespace app\common;
use yii\helpers\BaseFileHelper;
use Yii;
/**
* Class FileHelper
* @package common\helpers
* @author jianyan74 <751393839@qq.com>
*/
class FileHelper extends BaseFileHelper
{
public $_speed = 0;
/**
* 检测目录并循环创建目录
*
* @param $catalogue
*/
public static function mkdirs($catalogue)
{
if (!file_exists($catalogue)) {
self::mkdirs(dirname($catalogue));
mkdir($catalogue, 0777);
exec('chown -R www.www '.$catalogue);
}
return true;
}
/**
* 写入日志
*
* @param $path
* @param $content
* @return bool|int
*/
public static function writeLog($path, $content)
{
$use_num = self::sysProbe();
// $use_num = Yii::$app->redis->get(CacheKeyEnum::SYSTEM_PROBE);
if ($use_num > 98) {
return false;
}
self::mkdirs(dirname($path));
return file_put_contents($path, date('Y-m-d H:i:s') . ">>>" . $content . "\r\n", FILE_APPEND);
}
/**
* 检测磁盘空间
* @return bool|int|string
*/
public static function sysProbe()
{
$total = round(@disk_total_space(".") / (1024 * 1024 * 1024), 2);
$free = round(@disk_free_space(".") / (1024 * 1024 * 1024), 2);
$use_num = intval($total - $free) ? : 1;
// exec("df -h", $systemInfo);
// $disk = $systemInfo[5] ?? $systemInfo[1]; //没有找到其他磁盘就默认第一个
// $use_num = 1;
// if ($disk) {
// $use_num = trim(substr($disk, -10, -7)) ? : 1; //媒介保后端服务器磁盘用量
// }
// Yii::$app->redis->setex(CacheKeyEnum::SYSTEM_PROBE, 3600, $use_num);
return $use_num;
}
/**
* 获取文件夹大小
*
* @param string $dir 根文件夹路径
* @return int
*/
public static function getDirSize($dir)
{
$handle = opendir($dir);
$sizeResult = 0;
while (false !== ($FolderOrFile = readdir($handle))) {
if ($FolderOrFile != "." && $FolderOrFile != "..") {
if (is_dir("$dir/$FolderOrFile")) {
$sizeResult += self::getDirSize("$dir/$FolderOrFile");
}
else {
$sizeResult += filesize("$dir/$FolderOrFile");
}
}
}
closedir($handle);
return $sizeResult;
}
/**
* 基于数组创建目录
*
* @param $files
*/
public static function createDirOrFiles($files)
{
foreach ($files as $key => $value) {
if (substr($value, -1) == '/') {
mkdir($value);
}
else {
file_put_contents($value, '');
}
}
}
/**
* 文件大小字节转换对应的单位
* @param $size
* @return string
*/
public static function convert($size)
{
$unit = array('b','kb','MB','GB','tb','pb');
return round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . '' . $unit[$i];
}
public static function downloadVideo($url)
{
// $is_url = Url::isUrl($url);
// if (!$is_url) {
// exit('不是正确的链接地址'); //exit掉下载下来打开会显示无法播放格式不支持文件已损坏等
// }
//获取文件信息
// $fileExt = pathinfo($url);
//获取文件的扩展名
// $allowDownExt = array ('mp4', 'mov');
//检测文件类型是否允许下载
// if (!in_array($fileExt['extension'], $allowDownExt)) {
// exit('不支持该格式');
// }
// 设置浏览器下载的文件名,这里还以原文件名一样
$filename = basename($url);
// 获取远程文件大小
// 注意filesize()无法获取远程文件大小
$headers = get_headers($url, 1);
$fileSize = $headers['Content-Length'];
if (ini_get('zlib.output_compression')) {
ini_set('zlib.output_compression', 'Off');
}
header_remove('Content-Encoding');
// 设置header头
// 因为不知道文件是什么类型的,告诉浏览器输出的是字节流
header('Content-Type: application/octet-stream');
// 告诉浏览器返回的文件大小类型是字节
header('Accept-Ranges:bytes');
// 告诉浏览器返回的文件大小
header('Content-Length: ' . $fileSize);
// 告诉浏览器文件作为附件处理并且设定最终下载完成的文件名称
header('Content-Disposition: attachment; filename="' . $filename . '"');
//针对大文件规定每次读取文件的字节数为4096字节直接输出数据
$read_buffer = 4096; //4096
$handle = fopen($url, 'rb');
//总的缓冲的字节数
$sum_buffer = 0;
//只要没到文件尾,就一直读取
while (!feof($handle) && $sum_buffer < $fileSize) {
echo fread($handle, $read_buffer);
$sum_buffer += $read_buffer;
}
fclose($handle);
exit;
}
/**
* @param String $file 要下载的文件路径
* @param String $name 文件名称,为空则与下载的文件名称一样
* @param boolean $reload 是否开启断点续传
* @return string
*/
public static function downloadFile($file, $name = '', $reload = false)
{
$log_path = Yii::getAlias('@runtime') . '/api/' . date('Ym') . '/' . date('d') . '/download.txt';
FileHelper::writeLog($log_path, $file);
$fp = fopen($file, 'rb');
if ($fp) {
if ($name == '') {
$name = basename($file);
}
$header_array = get_headers($file, true);
// 下载本地文件,获取文件大小
if (!$header_array) {
$file_size = filesize($file);
} else {
$file_size = $header_array['Content-Length'];
}
FileHelper::writeLog($log_path, json_encode($_SERVER, JSON_UNESCAPED_UNICODE));
if (isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])) {
$ranges = self::getRange($file_size);
} else {
//第一次连接
$size2 = $file_size - 1;
header("Content-Range: bytes 0-$size2/$file_size"); //Content-Range: bytes 0-4988927/4988928
header("Content-Length: " . $file_size); //输出总长
}
$ua = $_SERVER["HTTP_USER_AGENT"];//判断是什么类型浏览器
header('cache-control:public');
header('content-type:application/octet-stream');
$encoded_filename = urlencode($name);
$encoded_filename = str_replace("+", "%20", $encoded_filename);
//解决下载文件名乱码
if (preg_match("/MSIE/", $ua) || preg_match("/Trident/", $ua)) {
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
} else if (preg_match("/Firefox/", $ua)) {
header('Content-Disposition: attachment; filename*="utf8\'\'' . $name . '"');
} else if (preg_match("/Chrome/", $ua)) {
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
} else {
header('Content-Disposition: attachment; filename="' . $name . '"');
}
//header('Content-Disposition: attachment; filename="' . $name . '"');
if ($reload && $ranges != null) { // 使用续传
header('HTTP/1.1 206 Partial Content');
header('Accept-Ranges:bytes');
// 剩余长度
header(sprintf('content-length:%u', $ranges['end'] - $ranges['start']));
// range信息
header(sprintf('content-range:bytes %s-%s/%s', $ranges['start'], $ranges['end'], $file_size));
FileHelper::writeLog($log_path, sprintf('content-length:%u', $ranges['end'] - $ranges['start']));
// fp指针跳到断点位置
fseek($fp, sprintf('%u', $ranges['start']));
} else {
header('HTTP/1.1 200 OK');
header('content-length:' . $file_size);
}
while (!feof($fp)) {
echo fread($fp, 4096);
ob_flush();
}
($fp != null) && fclose($fp);
} else {
return '';
}
}
/** 设置下载速度
* @param int $speed
*/
public function setSpeed($speed)
{
if (is_numeric($speed) && $speed > 16 && $speed < 4096) {
$this->_speed = $speed;
}
}
/** 获取header range信息
* @param int $file_size 文件大小
* @return Array
*/
private static function getRange($file_size)
{
if (isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])) {
$range = $_SERVER['HTTP_RANGE'];
$range = preg_replace('/[\s|,].*/', '', $range);
$range = explode('-', substr($range, 6));
if (count($range) < 2) {
$range[1] = $file_size;
}
$range = array_combine(array('start','end'), $range);
if (empty($range['start'])) {
$range['start'] = 0;
}
if (empty($range['end'])) {
$range['end'] = $file_size;
}
return $range;
}
return null;
}
}

16
common/ImageHelper.php Normal file
View File

@ -0,0 +1,16 @@
<?php
namespace app\common;
class ImageHelper
{
public static function imageMogr2H480(string $imageUrl): string
{
return "{$imageUrl}-h480";
}
public static function imageMogr2H1080(string $imageUrl): string
{
return "{$imageUrl}-h1080";
}
}

18
common/MobileHelper.php Normal file
View File

@ -0,0 +1,18 @@
<?php
namespace app\common;
class MobileHelper
{
public static function isValidChinaMobile($remarkDict): bool
{
if (is_string($remarkDict) && $remarkDict) {
$val = json_decode($remarkDict, true);
if (isset($val['是否为隐私号']) && $val['是否为隐私号'] == '是') {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,93 @@
<?php
namespace app\common;
use yii\data\ActiveDataProvider;
use yii\data\ArrayDataProvider;
use yii\db\ActiveQuery;
use yii\db\QueryInterface;
use yii\di\NotInstantiableException;
class PaginationHelper
{
/**
*
* @param \yii\db\ActiveQuery $query
* @param int $limit
* @param string $pageParam
* @param string $pageSizeParam
*
* @return \yii\data\ActiveDataProvider
*/
public static function createDataProvider($query, $limit = 10, $pageParam = 'page', $pageSizeParam = 'per_page')
{
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
//分页大小
'pageSize' => \Yii::$app->request->get($pageSizeParam) ?: $limit,
//设置地址栏当前页数参数名
'pageParam' => $pageParam,
//设置地址栏分页大小参数名
'pageSizeParam' => $pageSizeParam,
],
]);
return $dataProvider;
}
/**
* @param $query
* @param int $limit
* @param string $pageParam
* @param string $pageSizeParam
*
* @return \yii\db\QueryInterface
* @throws \yii\di\NotInstantiableException
*/
public static function createQueryProvider($query, $limit = 10, $pageParam = 'page', $pageSizeParam = 'limit')
{
$param = \Yii::$app->request->get();
$pageSize = $param['limit'] ?: $param[$pageSizeParam];
if ($query instanceof QueryInterface) {
return $query->limit($pageSize)->offset(($param[$pageParam] - 1) * $pageSize);
}
throw new NotInstantiableException('not instanceof QueryInterFace');
}
/**
* @param array $array
* @param int $limit
* @param string $pageParam
* @param string $pageSizeParam
* @param array $orderFields
*
* @return ArrayDataProvider
*/
public static function createArrayDataProvider($array = [], $orderFields = [], $limit = 10, $pageParam = 'page', $pageSizeParam = 'limit')
{
$attributes = array_keys($orderFields);
$order = $orderFields;
$dataProvider = new ArrayDataProvider([
'allModels' => $array,
'sort' => [
'attributes' => $attributes,
'defaultOrder' => $order
],
'pagination' => [
//分页大小
'pageSize' => \Yii::$app->request->get($pageSizeParam, 10),
//设置地址栏当前页数参数名
'pageParam' => $pageParam,
//设置地址栏分页大小参数名
'pageSizeParam' => $pageSizeParam,
],
]);
return $dataProvider;
}
}

11
common/SaltHelper.php Normal file
View File

@ -0,0 +1,11 @@
<?php
namespace app\common;
class SaltHelper
{
public static function addSalt(string $data)
{
return $data . \Yii::$app->params['salt'];
}
}