优化流量日志中间件

This commit is contained in:
taoser 2024-04-01 10:24:38 +08:00
parent a5acd6cb6e
commit 91bd9d28c2
23 changed files with 1000 additions and 245 deletions

View File

@ -38,6 +38,9 @@ class User extends AdminController
if(Request::isAjax()){ if(Request::isAjax()){
$datas = Request::only(['id','name','email','sex','status']); $datas = Request::only(['id','name','email','sex','status']);
$map = array_filter($datas,[$this,'filtrArr']); $map = array_filter($datas,[$this,'filtrArr']);
if(!empty($map['id'])) {
$map['id'] = (int) $map['id'];
}
$user = Db::name('user')->where(['delete_time'=>0])->where($map)->order('id desc')->paginate([ $user = Db::name('user')->where(['delete_time'=>0])->where($map)->order('id desc')->paginate([
'list_rows' => input('limit'), 'list_rows' => input('limit'),

View File

@ -12,6 +12,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>{block name="title"}TaoLerCMS后台管理系统{/block}</title> <title>{block name="title"}TaoLerCMS后台管理系统{/block}</title>
<link rel="stylesheet" href="/static/component/pear/css/pear.css" /> <link rel="stylesheet" href="/static/component/pear/css/pear.css" />
{block name="head"}内容{/block}
</head> </head>
<body class="pear-container"> <body class="pear-container">
{block name="body"}内容{/block} {block name="body"}内容{/block}

View File

@ -8,9 +8,9 @@
</head> </head>
<body class="pear-container"> <body class="pear-container">
<div class="layui-fluid" id="component-tabs"> <div class="layui-fluid" id="component-tabs">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-body"> <div class="layui-card-body">
<div class="layui-tab layui-tab-brief" lay-filter="server-tabs-brief"> <div class="layui-tab layui-tab-brief" lay-filter="server-tabs-brief" lay-allowclose="true">
<ul class="layui-tab-title"> <ul class="layui-tab-title">
<li lay-id="vip" class="layui-this">用户等级</li> <li lay-id="vip" class="layui-this">用户等级</li>
</ul> </ul>
@ -68,6 +68,7 @@
</div> </div>
{:hook('signadminhook')} {:hook('signadminhook')}
</div> </div>
</div> </div>
</div> </div>

View File

@ -313,14 +313,17 @@ class Article extends Model
*/ */
public function getAllTags($tagId) public function getAllTags($tagId)
{ {
$allTags = $this::hasWhere('taglist',['tag_id'=>$tagId]) $arrId = Taglist::where('tag_id', $tagId)->column('article_id');
$allTags = $this::field('id,user_id,cate_id,title,create_time,is_hot')->where('id','in', $arrId)
->with(['user' => function($query){ ->with(['user' => function($query){
$query->field('id,name,nickname,user_img,area_id,vip'); $query->field('id,name,nickname,user_img,area_id,vip');
},'cate' => function($query){ },'cate' => function($query){
$query->where('delete_time',0)->field('id,catename,ename'); $query->where('delete_time',0)->field('id,catename,ename');
}]) }])
->where(['status'=>1]) ->where(['status'=>1])
->order('pv desc') ->order('id desc')
->limit(20)
->append(['url']) ->append(['url'])
->select() ->select()
->toArray(); ->toArray();
@ -337,14 +340,13 @@ class Article extends Model
*/ */
public function getRelationTags($tagId,$id,$limit) public function getRelationTags($tagId,$id,$limit)
{ {
$allTags = $this::hasWhere('taglist',['tag_id'=>$tagId]) $arrId = Taglist::where([
->with(['user' => function($query){ ['tag_id', '=', $tagId],
$query->field('id,name,nickname,user_img,area_id,vip'); ['article_id','<>',$id]
},'cate' => function($query){ ])->column('article_id');
$query->where('delete_time',0)->field('id,catename,ename');
}]) $allTags = $this::field('id,cate_id,title')->where('id', 'in', $arrId)
->where(['status'=>1]) ->where(['status'=>1])
// ->where('article.id', '<>', $id)
->order('pv desc') ->order('pv desc')
->limit($limit) ->limit($limit)
->append(['url']) ->append(['url'])
@ -377,7 +379,7 @@ class Article extends Model
['id', '>', $id], ['id', '>', $id],
['cate_id', '=', $cid], ['cate_id', '=', $cid],
['status', '=',1] ['status', '=',1]
])->limit(1)->append(['url'])->select()->toArray(); ])->order('id asc')->limit(1)->append(['url'])->select()->toArray();
return ['previous' => $previous, 'next' => $next]; return ['previous' => $previous, 'next' => $next];
} }

View File

@ -55,13 +55,13 @@ class Article extends BaseController
$assignArr = [ $assignArr = [
'ename'=>$ename, 'ename' => $ename,
'cateinfo'=> $cateInfo, 'cateinfo' => $cateInfo,
'type'=>$type, 'type' => $type,
'artList'=>$artList, 'artList' => $artList,
'artHot'=>$artHot, 'artHot' => $artHot,
'path'=>$path, 'path' => $path,
'jspage'=>'jie' 'jspage' => 'jie'
]; ];
View::assign($assignArr); View::assign($assignArr);
@ -96,8 +96,8 @@ class Article extends BaseController
// 标签 // 标签
$tags = []; $tags = [];
$relationArticle = []; $relationArticle = []; //相关帖子
$artTags = Db::name('taglist')->where('article_id',$id)->select(); $artTags = Db::name('taglist')->where('article_id', $id)->select();
if(count($artTags)) { if(count($artTags)) {
foreach($artTags as $v) { foreach($artTags as $v) {
$tag = Db::name('tag')->find($v['tag_id']); $tag = Db::name('tag')->find($v['tag_id']);
@ -139,22 +139,22 @@ class Article extends BaseController
$push_js = Db::name('push_jscode')->where(['delete_time'=>0,'type'=>1])->cache(true)->select(); $push_js = Db::name('push_jscode')->where(['delete_time'=>0,'type'=>1])->cache(true)->select();
View::assign([ View::assign([
'article' => $artDetail, 'article' => $artDetail,
'pv' => $pv, 'pv' => $pv,
'artHot' => $artHot, 'artHot' => $artHot,
'tags' => $tags, 'tags' => $tags,
'relationArticle' => $relationArticle, 'relationArticle' => $relationArticle,
'previous' => $previous, 'previous' => $previous,
'next' => $next, 'next' => $next,
'page' => $page, 'page' => $page,
'comments' => $comments, 'comments' => $comments,
'push_js' => $push_js, 'push_js' => $push_js,
'cid' => $id, 'cid' => $id,
'lrDate_time' => $lrDate_time, 'lrDate_time' => $lrDate_time,
'userZanList' => $userZanList, 'userZanList' => $userZanList,
'zanCount' => $zanCount, 'zanCount' => $zanCount,
'jspage' => 'jie', 'jspage' => 'jie',
'passJieMi' => session('art_pass_'.$id), 'passJieMi' => session('art_pass_'.$id),
$download, $download,
]); ]);
@ -179,7 +179,7 @@ class Article extends BaseController
$data = Request::only(['content','article_id','pid','to_user_id']); $data = Request::only(['content','article_id','pid','to_user_id']);
$data['user_id'] = $this->uid; $data['user_id'] = $this->uid;
$sendId = $data['user_id']; $sendId = $data['user_id'];
// halt($data);
$art = Db::name('article')->field('id,status,is_reply,delete_time')->find($data['article_id']); $art = Db::name('article')->field('id,status,is_reply,delete_time')->find($data['article_id']);
if($art['delete_time'] != 0 || $art['status'] != 1 || $art['is_reply'] != 1){ if($art['delete_time'] != 0 || $art['status'] != 1 || $art['is_reply'] != 1){
@ -294,15 +294,16 @@ class Article extends BaseController
Db::name('user_article_log')->where('id', $postLog['id'])->inc('user_postnum')->update(); Db::name('user_article_log')->where('id', $postLog['id'])->inc('user_postnum')->update();
// 获取到的最新ID // 获取到的最新ID
$aid = $result['data']['id']; $aid = $result['data']['id'];
//写入taglist表 //写入taglist表
$tagArr = []; if(!empty($tagId)) {
if(isset($tagId)) { $tagArr = [];
$tagIdArr = explode(',',$tagId); $tagIdArr = explode(',', $tagId);
foreach($tagIdArr as $tid) { foreach($tagIdArr as $tid) {
$tagArr[] = ['article_id'=>$aid,'tag_id'=>$tid,'create_time'=>time()]; $tagArr[] = [ 'article_id' => $aid, 'tag_id' => $tid, 'create_time'=>time()];
} }
} Db::name('taglist')->insertAll($tagArr);
Db::name('taglist')->insertAll($tagArr); }
// 清除文章tag缓存 // 清除文章tag缓存
Cache::tag('tagArtDetail')->clear(); Cache::tag('tagArtDetail')->clear();
@ -385,11 +386,11 @@ class Article extends BaseController
$result = $article->edit($data); $result = $article->edit($data);
if($result == 1) { if($result == 1) {
//处理标签 //处理标签
$artTags = Db::name('taglist')->where('article_id',$id)->column('tag_id','id'); if(!empty($tagId)) {
if(isset($tagId)) {
$tagIdArr = explode(',',$tagId); $tagIdArr = explode(',',$tagId);
$artTags = Db::name('taglist')->where('article_id',$id)->column('tag_id','id');
foreach($artTags as $aid => $tid) { foreach($artTags as $aid => $tid) {
if(!in_array($tid,$tagIdArr)){ if(!in_array($tid, $tagIdArr)){
//删除被取消的tag //删除被取消的tag
Db::name('taglist')->delete($aid); Db::name('taglist')->delete($aid);
} }

View File

@ -29,6 +29,8 @@ class Index extends BaseController
*/ */
public function index() public function index()
{ {
// $ip = file_get_contents('https://myip.ipip.net');
// echo "My public IP address is: " . $ip;
$types = input('type'); $types = input('type');
//置顶文章 //置顶文章
$artTop = Article::getArtTop(5); $artTop = Article::getArtTop(5);

View File

@ -15,7 +15,6 @@ use app\facade\Article;
use think\facade\View; use think\facade\View;
use think\facade\Request; use think\facade\Request;
use think\facade\Db; use think\facade\Db;
use app\common\model\Slider;
use app\common\model\Tag as TagModel; use app\common\model\Tag as TagModel;
class Tag extends BaseController class Tag extends BaseController
@ -31,22 +30,20 @@ class Tag extends BaseController
{ {
// //
$tagEname = Request::param('ename'); $tagEname = Request::param('ename');
$tag = Db::name('tag')->where('ename',$tagEname)->find(); $tag = Db::name('tag')->where('ename', $tagEname)->find();
$artList = Article::getAllTags($tag['id']); $artList = Article::getAllTags($tag['id']);
$slider = new Slider();
//首页右栏
$ad_comm = $slider->getSliderList(2);
// 查询热议 // 查询热议
$artHot = Article::getArtHot(10); $artHot = Article::getArtHot(10);
$assign = [ $assign = [
'tag'=>$tag, 'tag' => $tag,
'artList'=>$artList, 'artList' => $artList,
'ad_comm'=>$ad_comm, 'artHot' => $artHot,
'artHot'=>$artHot, 'jspage' => ''
'jspage'=>''
]; ];
View::assign($assign); View::assign($assign);
return View::fetch('index'); return View::fetch('index');
} }

View File

@ -19,7 +19,7 @@ class Auth
$request->uid = $data->uid; $request->uid = $data->uid;
} catch(\Exception $e) { } catch(\Exception $e) {
return $e->getMessage(); return json(['code' => -1, 'msg' => $e->getMessage()]);
} }
} else { } else {

View File

@ -1,17 +1,17 @@
<?php <?php
namespace app\middleware; namespace app\middleware;
use think\facade\Request;
use think\facade\Log; use think\facade\Log;
class Browse class Browse
{ {
public function handle($request, \Closure $next) public function handle($request, \Closure $next)
{ {
$agent = $_SERVER['HTTP_USER_AGENT']; $agent = $request->header('user-agent');
$ip = $_SERVER['REMOTE_ADDR']; $ip = $request->ip();
$url = Request::url(true); $url = $request->url(true);
Log::channel('browse')->info('browse:{agent} {ip} {url}',['agent'=>$agent,'url'=>$url,'ip'=>$ip]); Log::channel('browse')->info('browse:{agent} {ip} {url}',['agent'=>$agent,'url'=>$url,'ip'=>$ip]);
return $next($request);
return $next($request);
} }
} }

26
composer.lock generated
View File

@ -859,16 +859,16 @@
}, },
{ {
"name": "laravel/serializable-closure", "name": "laravel/serializable-closure",
"version": "v1.3.2", "version": "v1.3.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/serializable-closure.git", "url": "https://github.com/laravel/serializable-closure.git",
"reference": "076fe2cf128bd54b4341cdc6d49b95b34e101e4c" "reference": "3dbf8a8e914634c48d389c1234552666b3d43754"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/076fe2cf128bd54b4341cdc6d49b95b34e101e4c", "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3dbf8a8e914634c48d389c1234552666b3d43754",
"reference": "076fe2cf128bd54b4341cdc6d49b95b34e101e4c", "reference": "3dbf8a8e914634c48d389c1234552666b3d43754",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -915,7 +915,7 @@
"issues": "https://github.com/laravel/serializable-closure/issues", "issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure" "source": "https://github.com/laravel/serializable-closure"
}, },
"time": "2023-10-17T13:38:16+00:00" "time": "2023-11-08T14:08:06+00:00"
}, },
{ {
"name": "league/flysystem", "name": "league/flysystem",
@ -3202,16 +3202,16 @@
}, },
{ {
"name": "yzh52521/easyhttp", "name": "yzh52521/easyhttp",
"version": "v1.1.0", "version": "v1.1.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/yzh52521/easyhttp.git", "url": "https://github.com/yuanzhihai/easyhttp.git",
"reference": "78ec5cea1884d6da0709cac95a1e4d23fe9bfc65" "reference": "02bcf47eaf723520fa3905d0e6f1852168fe646c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/yzh52521/easyhttp/zipball/78ec5cea1884d6da0709cac95a1e4d23fe9bfc65", "url": "https://api.github.com/repos/yuanzhihai/easyhttp/zipball/02bcf47eaf723520fa3905d0e6f1852168fe646c",
"reference": "78ec5cea1884d6da0709cac95a1e4d23fe9bfc65", "reference": "02bcf47eaf723520fa3905d0e6f1852168fe646c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3247,10 +3247,10 @@
"phphttp" "phphttp"
], ],
"support": { "support": {
"issues": "https://github.com/yzh52521/easyhttp/issues", "issues": "https://github.com/yuanzhihai/easyhttp/issues",
"source": "https://github.com/yzh52521/easyhttp/tree/v1.1.0" "source": "https://github.com/yuanzhihai/easyhttp/tree/v1.1.3"
}, },
"time": "2023-08-31T06:20:52+00:00" "time": "2023-11-14T05:49:02+00:00"
} }
], ],
"packages-dev": [ "packages-dev": [

View File

@ -16,7 +16,7 @@ return [
// 应用名,此项不可更改 // 应用名,此项不可更改
'appname' => 'TaoLer', 'appname' => 'TaoLer',
// 版本配置 // 版本配置
'version' => '2.5.2', 'version' => '2.5.3',
// 加盐 // 加盐
'salt' => 'taoler', 'salt' => 'taoler',
// 数据库备份目录 // 数据库备份目录

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -910,17 +910,17 @@
}, },
{ {
"name": "laravel/serializable-closure", "name": "laravel/serializable-closure",
"version": "v1.3.2", "version": "v1.3.3",
"version_normalized": "1.3.2.0", "version_normalized": "1.3.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/serializable-closure.git", "url": "https://github.com/laravel/serializable-closure.git",
"reference": "076fe2cf128bd54b4341cdc6d49b95b34e101e4c" "reference": "3dbf8a8e914634c48d389c1234552666b3d43754"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/076fe2cf128bd54b4341cdc6d49b95b34e101e4c", "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3dbf8a8e914634c48d389c1234552666b3d43754",
"reference": "076fe2cf128bd54b4341cdc6d49b95b34e101e4c", "reference": "3dbf8a8e914634c48d389c1234552666b3d43754",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -932,7 +932,7 @@
"phpstan/phpstan": "^1.8.2", "phpstan/phpstan": "^1.8.2",
"symfony/var-dumper": "^5.4.11" "symfony/var-dumper": "^5.4.11"
}, },
"time": "2023-10-17T13:38:16+00:00", "time": "2023-11-08T14:08:06+00:00",
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
@ -3531,17 +3531,17 @@
}, },
{ {
"name": "yzh52521/easyhttp", "name": "yzh52521/easyhttp",
"version": "v1.1.0", "version": "v1.1.3",
"version_normalized": "1.1.0.0", "version_normalized": "1.1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/yzh52521/easyhttp.git", "url": "https://github.com/yuanzhihai/easyhttp.git",
"reference": "78ec5cea1884d6da0709cac95a1e4d23fe9bfc65" "reference": "02bcf47eaf723520fa3905d0e6f1852168fe646c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/yzh52521/easyhttp/zipball/78ec5cea1884d6da0709cac95a1e4d23fe9bfc65", "url": "https://api.github.com/repos/yuanzhihai/easyhttp/zipball/02bcf47eaf723520fa3905d0e6f1852168fe646c",
"reference": "78ec5cea1884d6da0709cac95a1e4d23fe9bfc65", "reference": "02bcf47eaf723520fa3905d0e6f1852168fe646c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3549,7 +3549,7 @@
"php": ">=7.2.5", "php": ">=7.2.5",
"psr/log": "^1.0|^2.0|^3.0" "psr/log": "^1.0|^2.0|^3.0"
}, },
"time": "2023-08-31T06:20:52+00:00", "time": "2023-11-14T05:49:02+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -3579,8 +3579,8 @@
"phphttp" "phphttp"
], ],
"support": { "support": {
"issues": "https://github.com/yzh52521/easyhttp/issues", "issues": "https://github.com/yuanzhihai/easyhttp/issues",
"source": "https://github.com/yzh52521/easyhttp/tree/v1.1.0" "source": "https://github.com/yuanzhihai/easyhttp/tree/v1.1.3"
}, },
"install-path": "../yzh52521/easyhttp" "install-path": "../yzh52521/easyhttp"
} }

View File

@ -3,7 +3,7 @@
'name' => 'taoser/taoler', 'name' => 'taoser/taoler',
'pretty_version' => '2.3.10.x-dev', 'pretty_version' => '2.3.10.x-dev',
'version' => '2.3.10.9999999-dev', 'version' => '2.3.10.9999999-dev',
'reference' => '3115f271141016645a6dadee3b74f71758c868fb', 'reference' => '1bc07dde67cd6605da4e8444bd50db23b3da2c0b',
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
@ -128,9 +128,9 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'laravel/serializable-closure' => array( 'laravel/serializable-closure' => array(
'pretty_version' => 'v1.3.2', 'pretty_version' => 'v1.3.3',
'version' => '1.3.2.0', 'version' => '1.3.3.0',
'reference' => '076fe2cf128bd54b4341cdc6d49b95b34e101e4c', 'reference' => '3dbf8a8e914634c48d389c1234552666b3d43754',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../laravel/serializable-closure', 'install_path' => __DIR__ . '/../laravel/serializable-closure',
'aliases' => array(), 'aliases' => array(),
@ -358,7 +358,7 @@
'taoser/taoler' => array( 'taoser/taoler' => array(
'pretty_version' => '2.3.10.x-dev', 'pretty_version' => '2.3.10.x-dev',
'version' => '2.3.10.9999999-dev', 'version' => '2.3.10.9999999-dev',
'reference' => '3115f271141016645a6dadee3b74f71758c868fb', 'reference' => '1bc07dde67cd6605da4e8444bd50db23b3da2c0b',
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
@ -536,9 +536,9 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'yzh52521/easyhttp' => array( 'yzh52521/easyhttp' => array(
'pretty_version' => 'v1.1.0', 'pretty_version' => 'v1.1.3',
'version' => '1.1.0.0', 'version' => '1.1.3.0',
'reference' => '78ec5cea1884d6da0709cac95a1e4d23fe9bfc65', 'reference' => '02bcf47eaf723520fa3905d0e6f1852168fe646c',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../yzh52521/easyhttp', 'install_path' => __DIR__ . '/../yzh52521/easyhttp',
'aliases' => array(), 'aliases' => array(),

View File

@ -508,8 +508,7 @@ class ReflectionClosure extends ReflectionFunction
break; break;
case 'id_name': case 'id_name':
switch ($token[0]) { switch ($token[0]) {
// named arguments... case $token[0] === ':' && $context !== 'instanceof':
case ':':
if ($lastState === 'closure' && $context === 'root') { if ($lastState === 'closure' && $context === 'root') {
$state = 'closure'; $state = 'closure';
$code .= $id_start.$token; $code .= $id_start.$token;

2
vendor/services.php vendored
View File

@ -1,5 +1,5 @@
<?php <?php
// This file is automatically generated at:2023-11-02 18:31:51 // This file is automatically generated at:2023-11-23 17:07:27
declare (strict_types = 1); declare (strict_types = 1);
return array ( return array (
0 => 'taoser\\addons\\Service', 0 => 'taoser\\addons\\Service',

View File

@ -13,6 +13,11 @@ gitee:[gitee.com/yzh52521/easyhttp](https://gitee.com/yzh52521/easyhttp "gitee.c
1. 增加 retry() 重试机制。 1. 增加 retry() 重试机制。
2. 增加 debug 日志调试功能。 2. 增加 debug 日志调试功能。
3. 增加 withHost 指定服务端base_url 3. 增加 withHost 指定服务端base_url
4. 增加 withBody 发送原始数据Raw请求
5. 增加 withMiddleware/withRequestMiddleware/withResponseMiddleware Guzzle 中间件
6. 增加 connectTimeout 设置等待服务器响应超时
7. 增加 sink 响应的主体部分将要保存的位置
8. 增加 maxRedirects 请求的重定向行为最大次数
# 安装说明 # 安装说明
@ -53,6 +58,7 @@ $response = Http::delete(...);
$response = Http::head(...); $response = Http::head(...);
$response = Http::options(...); $response = Http::options(...);
``` ```
###### 指定服务端base_url的请求 ###### 指定服务端base_url的请求
@ -61,6 +67,12 @@ $response = Http::options(...);
// 指定服务端base_url地址,最终请求地址为 https://serv.yzh52521.com/login // 指定服务端base_url地址,最终请求地址为 https://serv.yzh52521.com/login
$response = Http::withHost('https://serv.yzh52521.com')->post('/login'); $response = Http::withHost('https://serv.yzh52521.com')->post('/login');
```
##### 发送原始数据Raw请求
```php
$response = Http::withBody(
base64_encode($photo), 'image/jpeg'
)->post(...);
``` ```
###### 发送 Content-Type 编码请求 ###### 发送 Content-Type 编码请求
@ -114,8 +126,12 @@ $response = Http::withRedirect([
'protocols' => ['http', 'https'], 'protocols' => ['http', 'https'],
'track_redirects' => false 'track_redirects' => false
])->post(...); ])->post(...);
$response = Http::maxRedirects(5)->post(...);
``` ```
###### 携带认证的请求 ###### 携带认证的请求
```php ```php
@ -182,6 +198,12 @@ $response = Http::withProxy([
$response = Http::timeout(60)->post(...); $response = Http::timeout(60)->post(...);
``` ```
###### 设置等待服务器响应超时的最大值(单位秒)
```php
$response = Http::connectTimeout(60)->post(...);
```
###### 设置延迟时间(单位秒) ###### 设置延迟时间(单位秒)
```php ```php
@ -199,6 +221,42 @@ $response = Http::concurrency(10)->promise(...);
```php ```php
$response = Http::retry(3, 100)->post(...); $response = Http::retry(3, 100)->post(...);
``` ```
##### 响应的主体部分将要保存的位置
```php
$response = Http::sink('/path/to/file')->post(...);
```
#### Guzzle 中间件
```php
use GuzzleHttp\Middleware;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
$response = Http::withMiddleware(
Middleware::mapRequest(function (RequestInterface $request) {
$request = $request->withHeader('X-Example', 'Value');
return $request;
})
)->get('http://example.com');
………………
$response = Http::withRequestMiddleware(
function (RequestInterface $request) {
$request = $request->withHeader('X-Example', 'Value');
return $request;
}
)->get('http://example.com');
………………
$response = Http::withResponseMiddleware(
function (RequestInterface $response) {
$response = $response->getHeader('X-Example');
return $response;
}
)->get('http://example.com');
```
#### 异步请求 #### 异步请求
@ -206,22 +264,26 @@ $response = Http::retry(3, 100)->post(...);
use yzh52521\EasyHttp\Response; use yzh52521\EasyHttp\Response;
use yzh52521\EasyHttp\RequestException; use yzh52521\EasyHttp\RequestException;
Http::getAsync('http://easyhttp.yzh52521.cn/api/sleep3.json', ['token' => TOKEN], function (Response $response) { $promise = Http::getAsync('http://easyhttp.yzh52521.cn/api/sleep3.json', ['token' => TOKEN], function (Response $response) {
echo '异步请求成功,响应内容:' . $response->body() . PHP_EOL; echo '异步请求成功,响应内容:' . $response->body() . PHP_EOL;
}, function (RequestException $e) { }, function (RequestException $e) {
echo '异步请求异常,错误码:' . $e->getCode() . ',错误信息:' . $e->getMessage() . PHP_EOL; echo '异步请求异常,错误码:' . $e->getCode() . ',错误信息:' . $e->getMessage() . PHP_EOL;
}); });
$promise->wait();
echo json_encode(['code' => 200, 'msg' => '请求成功'], JSON_UNESCAPED_UNICODE) . PHP_EOL; echo json_encode(['code' => 200, 'msg' => '请求成功'], JSON_UNESCAPED_UNICODE) . PHP_EOL;
//输出 //输出
{"code":200,"msg":"请求成功"} {"code":200,"msg":"请求成功"}
异步请求成功,响应内容:{"code":200,"msg":"success","second":3} 异步请求成功,响应内容:{"code":200,"msg":"success","second":3}
Http::getAsync('http1://easyhttp.yzh52521.cn/api/sleep3.json', function (Response $response) { $promise = Http::getAsync('http1://easyhttp.yzh52521.cn/api/sleep3.json', function (Response $response) {
echo '异步请求成功,响应内容:' . $response->body() . PHP_EOL; echo '异步请求成功,响应内容:' . $response->body() . PHP_EOL;
}, function (RequestException $e) { }, function (RequestException $e) {
echo '异步请求异常,错误信息:' . $e->getMessage() . PHP_EOL; echo '异步请求异常,错误信息:' . $e->getMessage() . PHP_EOL;
}); });
$promise->wait();
echo json_encode(['code' => 200, 'msg' => '请求成功'], JSON_UNESCAPED_UNICODE) . PHP_EOL; echo json_encode(['code' => 200, 'msg' => '请求成功'], JSON_UNESCAPED_UNICODE) . PHP_EOL;
//输出 //输出
@ -239,6 +301,9 @@ Http::deleteAsync(...);
Http::headAsync(...); Http::headAsync(...);
Http::optionsAsync(...); Http::optionsAsync(...);
使用 等待异步回调处理完成
Http::wait();
``` ```
#### 异步并发请求 #### 异步并发请求
@ -253,12 +318,15 @@ $promises = [
Http::postAsync('http://easyhttp.yzh52521.cn/api/sleep2.json', ['name' => 'yzh52521']), Http::postAsync('http://easyhttp.yzh52521.cn/api/sleep2.json', ['name' => 'yzh52521']),
]; ];
Http::concurrency(10)->multiAsync($promises, function (Response $response, $index) { $pool=Http::concurrency(10)->multiAsync($promises, function (Response $response, $index) {
echo "发起第 $index 个异步请求,请求时长:" . $response->json()->second . '秒' . PHP_EOL; echo "发起第 $index 个异步请求,请求时长:" . $response->json()->second . '秒' . PHP_EOL;
}, function (RequestException $e, $index) { }, function (RequestException $e, $index) {
echo "发起第 $index 个请求失败,失败原因:" . $e->getMessage() . PHP_EOL; echo "发起第 $index 个请求失败,失败原因:" . $e->getMessage() . PHP_EOL;
}); });
$promise = $pool->promise();
$promise->wait();
//输出 //输出
发起第 1 个请求失败失败原因cURL error 1: Protocol "http1" not supported or disabled in libcurl (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) 发起第 1 个请求失败失败原因cURL error 1: Protocol "http1" not supported or disabled in libcurl (see https://curl.haxx.se/libcurl/c/libcurl-errors.html)
发起第 2 个异步请求请求时长2 秒 发起第 2 个异步请求请求时长2 秒
@ -306,6 +374,12 @@ Http::debug(Log::class)->post(...);
## 更新日志 ## 更新日志
### 2023-08-31
* 新增 withBody 可以发送原始数据Raw请求
* 新增 withMiddleware/withRequestMiddleware/withResponseMiddleware 支持Guzzle中间件
* 新增 connectTimeout 设置等待服务器响应超时
* 新增 sink 响应的主体部分将要保存的位置
* 新增 maxRedirects 请求的重定向行为最大次数
### 2022-05-11 ### 2022-05-11
* 新增removeBodyFormat() 用于withOptions 指定body时清除原由的bodyFromat * 新增removeBodyFormat() 用于withOptions 指定body时清除原由的bodyFromat
### 2022-05-10 ### 2022-05-10

View File

@ -11,11 +11,16 @@ class Facade
$this->facade = new $this->facade; $this->facade = new $this->facade;
} }
public function __call($name, $params) { public function __call($name, $params)
{
if (method_exists($this->facade, 'removeOptions')) {
call_user_func_array([$this->facade, 'removeOptions'], []);
}
return call_user_func_array([$this->facade, $name], $params); return call_user_func_array([$this->facade, $name], $params);
} }
public static function __callStatic($name, $params) { public static function __callStatic($name, $params)
{
return call_user_func_array([new static(), $name], $params); return call_user_func_array([new static(), $name], $params);
} }
} }

View File

@ -17,7 +17,7 @@ use GuzzleHttp\Exception\ConnectException;
* @method \yzh52521\EasyHttp\Response array() * @method \yzh52521\EasyHttp\Response array()
* @method \yzh52521\EasyHttp\Response json() * @method \yzh52521\EasyHttp\Response json()
* @method \yzh52521\EasyHttp\Response headers() * @method \yzh52521\EasyHttp\Response headers()
* @method \yzh52521\EasyHttp\Response header( string $header ) * @method \yzh52521\EasyHttp\Response header(string $header)
* @method \yzh52521\EasyHttp\Response status() * @method \yzh52521\EasyHttp\Response status()
* @method \yzh52521\EasyHttp\Response successful() * @method \yzh52521\EasyHttp\Response successful()
* @method \yzh52521\EasyHttp\Response ok() * @method \yzh52521\EasyHttp\Response ok()
@ -84,11 +84,11 @@ class Request
{ {
$this->client = $this->getInstance(); $this->client = $this->getInstance();
$this->bodyFormat = 'form_params'; $this->bodyFormat = 'form_params';
$this->options = [ $this->options = [
'http_errors' => false, 'http_errors' => false,
]; ];
$this->handlerStack = HandlerStack::create( new CurlHandler() ); $this->handlerStack = HandlerStack::create(new CurlHandler());
} }
/** /**
@ -96,9 +96,7 @@ class Request
*/ */
public function __destruct() public function __destruct()
{ {
if (!empty( $this->promises )) {
Promise\settle( $this->promises )->wait();
}
} }
/** /**
@ -109,17 +107,28 @@ class Request
{ {
$name = get_called_class(); $name = get_called_class();
if (!isset( self::$instances[$name] )) { if (!isset(self::$instances[$name])) {
self::$instances[$name] = new Client(); self::$instances[$name] = new Client();
} }
return self::$instances[$name]; return self::$instances[$name];
} }
public function removeOptions()
{
$this->bodyFormat = 'form_params';
$this->isRemoveBodyFormat = false;
$this->options = [
'http_errors' => false,
'verify' => false
];
return $this;
}
public function asForm() public function asForm()
{ {
$this->bodyFormat = 'form_params'; $this->bodyFormat = 'form_params';
$this->withHeaders( ['Content-Type' => 'application/x-www-form-urlencoded'] ); $this->withHeaders(['Content-Type' => 'application/x-www-form-urlencoded']);
return $this; return $this;
} }
@ -127,21 +136,21 @@ class Request
public function asJson() public function asJson()
{ {
$this->bodyFormat = 'json'; $this->bodyFormat = 'json';
$this->withHeaders( ['Content-Type' => 'application/json'] ); $this->withHeaders(['Content-Type' => 'application/json']);
return $this; return $this;
} }
public function asMultipart(string $name,string $contents,string $filename = null,array $headers = []) public function asMultipart(string $name, string $contents, string $filename = null, array $headers = [])
{ {
$this->bodyFormat = 'multipart'; $this->bodyFormat = 'multipart';
$this->options = array_filter( [ $this->options = array_filter([
'name' => $name, 'name' => $name,
'contents' => $contents, 'contents' => $contents,
'headers' => $headers, 'headers' => $headers,
'filename' => $filename, 'filename' => $filename,
] ); ]);
return $this; return $this;
} }
@ -182,25 +191,25 @@ class Request
public function withOptions(array $options) public function withOptions(array $options)
{ {
unset( $this->options[$this->bodyFormat],$this->options['body'] ); unset($this->options[$this->bodyFormat], $this->options['body']);
$this->options = array_merge_recursive( $this->options,$options ); $this->options = array_merge_recursive($this->options, $options);
return $this; return $this;
} }
public function withCert(string $path,string $password) public function withCert(string $path, string $password)
{ {
$this->options['cert'] = [$path,$password]; $this->options['cert'] = [$path, $password];
return $this; return $this;
} }
public function withHeaders(array $headers) public function withHeaders(array $headers)
{ {
$this->options = array_merge_recursive( $this->options,[ $this->options = array_merge_recursive($this->options, [
'headers' => $headers, 'headers' => $headers,
] ); ]);
return $this; return $this;
} }
@ -216,39 +225,39 @@ class Request
return $this; return $this;
} }
public function withBasicAuth(string $username,string $password) public function withBasicAuth(string $username, string $password)
{ {
$this->options['auth'] = [$username,$password]; $this->options['auth'] = [$username, $password];
return $this; return $this;
} }
public function withDigestAuth(string $username,string $password) public function withDigestAuth(string $username, string $password)
{ {
$this->options['auth'] = [$username,$password,'digest']; $this->options['auth'] = [$username, $password, 'digest'];
return $this; return $this;
} }
public function withUA(string $ua) public function withUA(string $ua)
{ {
$this->options['headers']['User-Agent'] = trim( $ua ); $this->options['headers']['User-Agent'] = trim($ua);
return $this; return $this;
} }
public function withToken(string $token,string $type = 'Bearer') public function withToken(string $token, string $type = 'Bearer')
{ {
$this->options['headers']['Authorization'] = trim( $type.' '.$token ); $this->options['headers']['Authorization'] = trim($type . ' ' . $token);
return $this; return $this;
} }
public function withCookies(array $cookies,string $domain) public function withCookies(array $cookies, string $domain)
{ {
$this->options = array_merge_recursive( $this->options,[ $this->options = array_merge_recursive($this->options, [
'cookies' => CookieJar::fromArray( $cookies,$domain ), 'cookies' => CookieJar::fromArray($cookies, $domain),
] ); ]);
return $this; return $this;
} }
@ -302,9 +311,9 @@ class Request
return $this; return $this;
} }
public function retry(int $retries = 1,int $sleep = 0) public function retry(int $retries = 1, int $sleep = 0)
{ {
$this->handlerStack->push( ( new Retry() )->handle( $retries,$sleep ) ); $this->handlerStack->push((new Retry())->handle($retries, $sleep));
$this->options['handler'] = $this->handlerStack; $this->options['handler'] = $this->handlerStack;
@ -351,17 +360,17 @@ class Request
public function debug($class) public function debug($class)
{ {
$logger = new Logger( function ($level,$message,array $context) use ($class) { $logger = new Logger(function ($level, $message, array $context) use ($class) {
$class::log( $level,$message ); $class::log($level, $message);
},function ($request,$response,$reason) { }, function ($request, $response, $reason) {
$requestBody = $request->getBody(); $requestBody = $request->getBody();
$requestBody->rewind(); $requestBody->rewind();
//请求头 //请求头
$requestHeaders = []; $requestHeaders = [];
foreach ( (array)$request->getHeaders() as $k => $vs ) { foreach ((array)$request->getHeaders() as $k => $vs) {
foreach ( $vs as $v ) { foreach ($vs as $v) {
$requestHeaders[] = "$k: $v"; $requestHeaders[] = "$k: $v";
} }
} }
@ -369,8 +378,8 @@ class Request
//响应头 //响应头
$responseHeaders = []; $responseHeaders = [];
foreach ( (array)$response->getHeaders() as $k => $vs ) { foreach ((array)$response->getHeaders() as $k => $vs) {
foreach ( $vs as $v ) { foreach ($vs as $v) {
$responseHeaders[] = "$k: $v"; $responseHeaders[] = "$k: $v";
} }
} }
@ -379,7 +388,7 @@ class Request
$path = $uri->getPath(); $path = $uri->getPath();
if ($query = $uri->getQuery()) { if ($query = $uri->getQuery()) {
$path .= '?'.$query; $path .= '?' . $query;
} }
return sprintf( return sprintf(
@ -388,175 +397,175 @@ class Request
$request->getMethod(), $request->getMethod(),
$path, $path,
$request->getProtocolVersion(), $request->getProtocolVersion(),
join( "\r\n",$requestHeaders ), join("\r\n", $requestHeaders),
$requestBody->getContents(), $requestBody->getContents(),
$response->getProtocolVersion(), $response->getProtocolVersion(),
$response->getStatusCode(), $response->getStatusCode(),
$response->getReasonPhrase(), $response->getReasonPhrase(),
join( "\r\n",$responseHeaders ), join("\r\n", $responseHeaders),
$response->getBody()->getContents() $response->getBody()->getContents()
); );
} ); });
$this->handlerStack->push( $logger ); $this->handlerStack->push($logger);
$this->options['handler'] = $this->handlerStack; $this->options['handler'] = $this->handlerStack;
return $this; return $this;
} }
public function attach(string $name,string $contents,string $filename = null,array $headers = []) public function attach(string $name, string $contents, string $filename = null, array $headers = [])
{ {
$this->options['multipart'] = array_filter( [ $this->options['multipart'] = array_filter([
'name' => $name, 'name' => $name,
'contents' => $contents, 'contents' => $contents,
'headers' => $headers, 'headers' => $headers,
'filename' => $filename, 'filename' => $filename,
] ); ]);
return $this; return $this;
} }
public function get(string $url,array $query = []) public function get(string $url, array $query = [])
{ {
$params= parse_url( $url,PHP_URL_QUERY ); $params = parse_url($url, PHP_URL_QUERY);
parse_str( $params?:'',$result ); parse_str($params ?: '', $result);
$this->options['query'] = array_merge( $result,$query ); $this->options['query'] = array_merge($result, $query);
return $this->request( 'GET',$url,$query ); return $this->request('GET', $url, $query);
} }
public function post(string $url,array $data = []) public function post(string $url, array $data = [])
{ {
$this->options[$this->bodyFormat] = $data; $this->options[$this->bodyFormat] = $data;
return $this->request( 'POST',$url,$data ); return $this->request('POST', $url, $data);
} }
public function patch(string $url,array $data = []) public function patch(string $url, array $data = [])
{ {
$this->options[$this->bodyFormat] = $data; $this->options[$this->bodyFormat] = $data;
return $this->request( 'PATCH',$url,$data ); return $this->request('PATCH', $url, $data);
} }
public function put(string $url,array $data = []) public function put(string $url, array $data = [])
{ {
$this->options[$this->bodyFormat] = $data; $this->options[$this->bodyFormat] = $data;
return $this->request( 'PUT',$url,$data ); return $this->request('PUT', $url, $data);
} }
public function delete(string $url,array $data = []) public function delete(string $url, array $data = [])
{ {
$this->options[$this->bodyFormat] = $data; $this->options[$this->bodyFormat] = $data;
return $this->request( 'DELETE',$url,$data ); return $this->request('DELETE', $url, $data);
} }
public function head(string $url,array $data = []) public function head(string $url, array $data = [])
{ {
$this->options[$this->bodyFormat] = $data; $this->options[$this->bodyFormat] = $data;
return $this->request( 'HEAD',$url,$data ); return $this->request('HEAD', $url, $data);
} }
public function options(string $url,array $data = []) public function options(string $url, array $data = [])
{ {
$this->options[$this->bodyFormat] = $data; $this->options[$this->bodyFormat] = $data;
return $this->request( 'OPTIONS',$url,$data ); return $this->request('OPTIONS', $url, $data);
} }
public function getAsync(string $url,$query = null,callable $success = null,callable $fail = null) public function getAsync(string $url, $query = null, callable $success = null, callable $fail = null)
{ {
is_callable( $query ) || $this->options['query'] = $query; is_callable($query) || $this->options['query'] = $query;
return $this->requestAsync( 'GET',$url,$query,$success,$fail ); return $this->requestAsync('GET', $url, $query, $success, $fail);
} }
public function postAsync(string $url,$data = null,callable $success = null,callable $fail = null) public function postAsync(string $url, $data = null, callable $success = null, callable $fail = null)
{ {
is_callable( $data ) || $this->options[$this->bodyFormat] = $data; is_callable($data) || $this->options[$this->bodyFormat] = $data;
return $this->requestAsync( 'POST',$url,$data,$success,$fail ); return $this->requestAsync('POST', $url, $data, $success, $fail);
} }
public function patchAsync(string $url,$data = null,callable $success = null,callable $fail = null) public function patchAsync(string $url, $data = null, callable $success = null, callable $fail = null)
{ {
is_callable( $data ) || $this->options[$this->bodyFormat] = $data; is_callable($data) || $this->options[$this->bodyFormat] = $data;
return $this->requestAsync( 'PATCH',$url,$data,$success,$fail ); return $this->requestAsync('PATCH', $url, $data, $success, $fail);
} }
public function putAsync(string $url,$data = null,callable $success = null,callable $fail = null) public function putAsync(string $url, $data = null, callable $success = null, callable $fail = null)
{ {
is_callable( $data ) || $this->options[$this->bodyFormat] = $data; is_callable($data) || $this->options[$this->bodyFormat] = $data;
return $this->requestAsync( 'PUT',$url,$data,$success,$fail ); return $this->requestAsync('PUT', $url, $data, $success, $fail);
} }
public function deleteAsync(string $url,$data = null,callable $success = null,callable $fail = null) public function deleteAsync(string $url, $data = null, callable $success = null, callable $fail = null)
{ {
is_callable( $data ) || $this->options[$this->bodyFormat] = $data; is_callable($data) || $this->options[$this->bodyFormat] = $data;
return $this->requestAsync( 'DELETE',$url,$data,$success,$fail ); return $this->requestAsync('DELETE', $url, $data, $success, $fail);
} }
public function headAsync(string $url,$data = null,callable $success = null,callable $fail = null) public function headAsync(string $url, $data = null, callable $success = null, callable $fail = null)
{ {
is_callable( $data ) || $this->options[$this->bodyFormat] = $data; is_callable($data) || $this->options[$this->bodyFormat] = $data;
return $this->requestAsync( 'HEAD',$url,$data,$success,$fail ); return $this->requestAsync('HEAD', $url, $data, $success, $fail);
} }
public function optionsAsync(string $url,$data = null,callable $success = null,callable $fail = null) public function optionsAsync(string $url, $data = null, callable $success = null, callable $fail = null)
{ {
is_callable( $data ) || $this->options[$this->bodyFormat] = $data; is_callable($data) || $this->options[$this->bodyFormat] = $data;
return $this->requestAsync( 'OPTIONS',$url,$data,$success,$fail ); return $this->requestAsync('OPTIONS', $url, $data, $success, $fail);
} }
public function multiAsync(array $promises,callable $success = null,callable $fail = null) public function multiAsync(array $promises, callable $success = null, callable $fail = null)
{ {
$count = count( $promises ); $count = count($promises);
$this->concurrency = $this->concurrency ?: $count; $this->concurrency = $this->concurrency ?: $count;
$requests = function () use ($promises) { $requests = function () use ($promises) {
foreach ( $promises as $promise ) { foreach ($promises as $promise) {
yield function () use ($promise) { yield function () use ($promise) {
return $promise; return $promise;
}; };
} }
}; };
$fulfilled = function ($response,$index) use ($success) { $fulfilled = function ($response, $index) use ($success) {
if (!is_null( $success )) { if (!is_null($success)) {
$response = $this->response( $response ); $response = $this->response($response);
call_user_func_array( $success,[$response,$index] ); call_user_func_array($success, [$response, $index]);
} }
}; };
$rejected = function ($exception,$index) use ($fail) { $rejected = function ($exception, $index) use ($fail) {
if (!is_null( $fail )) { if (!is_null($fail)) {
$exception = $this->exception( $exception ); $exception = $this->exception($exception);
call_user_func_array( $fail,[$exception,$index] ); call_user_func_array($fail, [$exception, $index]);
} }
}; };
$pool = new Pool( $this->client,$requests(),[ $pool = new Pool($this->client, $requests(), [
'concurrency' => $this->concurrency, 'concurrency' => $this->concurrency,
'fulfilled' => $fulfilled, 'fulfilled' => $fulfilled,
'rejected' => $rejected, 'rejected' => $rejected,
] ); ]);
$pool->promise(); $pool->promise();
return $pool; return $pool;
} }
protected function request(string $method,string $url,array $options = []) protected function request(string $method, string $url, array $options = [])
{ {
if (isset($this->options[$this->bodyFormat])) { if (isset($this->options[$this->bodyFormat])) {
$this->options[$this->bodyFormat] = $options; $this->options[$this->bodyFormat] = $options;
@ -564,13 +573,13 @@ class Request
$this->options[$this->bodyFormat] = $this->pendingBody; $this->options[$this->bodyFormat] = $this->pendingBody;
} }
if ($this->isRemoveBodyFormat) { if ($this->isRemoveBodyFormat) {
unset( $this->options[$this->bodyFormat] ); unset($this->options[$this->bodyFormat]);
} }
try { try {
$response = $this->client->request( $method,$url,$this->options ); $response = $this->client->request($method, $url, $this->options);
return $this->response( $response ); return $this->response($response);
} catch ( ConnectException $e ) { } catch (ConnectException $e) {
throw new ConnectionException( $e->getMessage(),0,$e ); throw new ConnectionException($e->getMessage(), 0, $e);
} }
} }
@ -583,7 +592,7 @@ class Request
* @throws ConnectionException * @throws ConnectionException
* @throws \GuzzleHttp\Exception\GuzzleException * @throws \GuzzleHttp\Exception\GuzzleException
*/ */
public function client(string $method,string $url,array $options = []) public function client(string $method, string $url, array $options = [])
{ {
if (isset($this->options[$this->bodyFormat])) { if (isset($this->options[$this->bodyFormat])) {
$this->options[$this->bodyFormat] = $options; $this->options[$this->bodyFormat] = $options;
@ -591,16 +600,16 @@ class Request
$this->options[$this->bodyFormat] = $this->pendingBody; $this->options[$this->bodyFormat] = $this->pendingBody;
} }
if ($this->isRemoveBodyFormat) { if ($this->isRemoveBodyFormat) {
unset( $this->options[$this->bodyFormat] ); unset($this->options[$this->bodyFormat]);
} }
try { try {
if (empty( $options )) { if (empty($options)) {
$options = $this->options; $options = $this->options;
} }
$response = $this->client->request( $method,$url,$options ); $response = $this->client->request($method, $url, $options);
return $this->response( $response ); return $this->response($response);
} catch ( ConnectException $e ) { } catch (ConnectException $e) {
throw new ConnectionException( $e->getMessage(),0,$e ); throw new ConnectionException($e->getMessage(), 0, $e);
} }
} }
@ -612,7 +621,7 @@ class Request
* @return Response * @return Response
* @throws ConnectionException * @throws ConnectionException
*/ */
public function clientAsync(string $method,string $url,array $options = []) public function clientAsync(string $method, string $url, array $options = [])
{ {
if (isset($this->options[$this->bodyFormat])) { if (isset($this->options[$this->bodyFormat])) {
$this->options[$this->bodyFormat] = $options; $this->options[$this->bodyFormat] = $options;
@ -620,23 +629,23 @@ class Request
$this->options[$this->bodyFormat] = $this->pendingBody; $this->options[$this->bodyFormat] = $this->pendingBody;
} }
if ($this->isRemoveBodyFormat) { if ($this->isRemoveBodyFormat) {
unset( $this->options[$this->bodyFormat] ); unset($this->options[$this->bodyFormat]);
} }
try { try {
if (empty( $options )) { if (empty($options)) {
$options = $this->options; $options = $this->options;
} }
$response = $this->client->requestAsync( $method,$url,$options ); $response = $this->client->requestAsync($method, $url, $options);
return $this->response( $response ); return $this->response($response);
} catch ( ConnectException $e ) { } catch (ConnectException $e) {
throw new ConnectionException( $e->getMessage(),0,$e ); throw new ConnectionException($e->getMessage(), 0, $e);
} }
} }
protected function requestAsync(string $method, string $url, $options = null, callable $success = null, callable $fail = null) protected function requestAsync(string $method, string $url, $options = null, callable $success = null, callable $fail = null)
{ {
if (is_callable( $options )) { if (is_callable($options)) {
$successCallback = $options; $successCallback = $options;
$failCallback = $success; $failCallback = $success;
} else { } else {
@ -651,52 +660,52 @@ class Request
} }
if ($this->isRemoveBodyFormat) { if ($this->isRemoveBodyFormat) {
unset( $this->options[$this->bodyFormat] ); unset($this->options[$this->bodyFormat]);
} }
try { try {
$promise = $this->client->requestAsync( $method,$url,$this->options ); $promise = $this->client->requestAsync($method, $url, $this->options);
$fulfilled = function ($response) use ($successCallback) { $fulfilled = function ($response) use ($successCallback) {
if (!is_null( $successCallback )) { if (!is_null($successCallback)) {
$response = $this->response( $response ); $response = $this->response($response);
call_user_func_array( $successCallback,[$response] ); call_user_func_array($successCallback, [$response]);
} }
}; };
$rejected = function ($exception) use ($failCallback) { $rejected = function ($exception) use ($failCallback) {
if (!is_null( $failCallback )) { if (!is_null($failCallback)) {
$exception = $this->exception( $exception ); $exception = $this->exception($exception);
call_user_func_array( $failCallback,[$exception] ); call_user_func_array($failCallback, [$exception]);
} }
}; };
$promise->then( $fulfilled,$rejected ); $promise->then($fulfilled, $rejected);
$this->promises[] = $promise; $this->promises[] = $promise;
return $promise; return $promise;
} catch ( ConnectException $e ) { } catch (ConnectException $e) {
throw new ConnectionException( $e->getMessage(),0,$e ); throw new ConnectionException($e->getMessage(), 0, $e);
} }
} }
public function wait() public function wait()
{ {
if (!empty($this->promises)) { if (!empty($this->promises)) {
Promise\settle($this->promises)->wait(); \GuzzleHttp\Promise\Utils($this->promises)->wait();
} }
$this->promises = []; $this->promises = [];
} }
protected function response($response) protected function response($response)
{ {
return new Response( $response ); return new Response($response);
} }
protected function exception($exception) protected function exception($exception)
{ {
return new RequestException( $exception ); return new RequestException($exception);
} }
} }

View File

@ -0,0 +1,141 @@
{extend name="public/base" /}
{block name="title"}{$cateinfo.catename} - {$sysInfo.webname}{/block}
{block name="keywords"}{$cateinfo.catename},{$sysInfo.webname}{/block}
{block name="description"}{$cateinfo.desc}{/block}
{block name="ogtitle"}<meta property="og:title" content="{$cateinfo.catename} - {$sysInfo.webname}">{/block}
{block name="ogdescription"}<meta property="og:description" content="{$cateinfo.desc}" />{/block}
{block name="meta"}
<!-- SEO优化 -->
<meta name="Copyright" content="{$sysInfo.webname}">
<meta property="og:type" content="website"/>
<meta property="og:url" content="{$Request.domain}"/>
<meta property="og:site_name" content="{$sysInfo.webname}"/>
<meta property="og:image" content=""/>
{/block}
{block name="link"}
<!-- 特效丶样式 -->
<link rel="dns-prefetch" href="//q4.qlogo.cn">
<link rel="shortcut icon" type="image/x-icon" href="{$Request.domain}/favicon.ico"/>
<link rel="apple-touch-icon" sizes="180x180" href=""/>
<link rel="apple-touch-icon-precomposed" href=""/>
<link rel="stylesheet" href="{$Request.domain}/view/common/blog/css/style.css" type="text/css" charset="utf-8"/>
<script src="/static/jquery-3.6.0.min.js"></script>
{/block}
{block name="column"}{include file="/public/column" /}{/block}
{block name="content"}
<main class="py-2 py-md-2 pb-3">
<div class="layui-container">
<div class="layui-row layui-col-space15">
<div class="layui-col-md8">
<div class="post"><h1>{$sysInfo.webname}</h1></div>
<section id="main" class="list-home list-grid list-grid-padding">
{article:list}
<article class="list-item block card-plain">
{if getOnepic($article.content)}
<figure class="media media-3x2 col-4 col-md-4 d-none d-md-block">
<a class="media-content" href="{article:link /}" title="{article:title /}">
<img src="{:getOnepic($article.content)}" width="233" height="155" alt="{article:title /}">
</a>
</figure>
{/if}
<div class="list-width list-content">
<div class="list-body">
<h3>
<a href="{article:link /}" title="{article:title /}" class="list-title fanpian">{article:title /}</a>
</h3>
<div class="list-desc d-block d-md-block text-sm text-secondary my-3">
<p class="h-3x">{:getArtContent($article.content)}</p>
</div>
</div>
<div class="list-footer">
<div class="d-flex flex-fill align-items-center text-muted text-xs">
<time class="d-inline-block" datetime="{$article.create_time|date='Y-m-d'}">{$article.create_time|date='Y-m-d'}</time>
<div class="d-inline-block mx-1 mx-md-2">
<i class="text-primary">·</i>
</div>
<div class="d-inline-block">
<a href="{article:user name='link' /}" class="text-muted" title="发布于{article:auther /}" rel="category">{article:auther /}</a>
{$article.has_img ?= '<span><i class="layui-icon layui-icon-picture" style="color: #5FB878;"></i></span>'}
{$article.has_video ?= '<span><i class="layui-icon layui-icon-play" style="color: #FF5722;"></i></span>'}
{$article.has_audio ?= '<span><i class="layui-icon layui-icon-speaker" style="color: #000000;"></i></span>'}
{$article.read_type ?= '<span><i class="layui-icon layui-icon-password" style="color: #FF5722;"></i></span>'}
{$article.upzip ?= '<span><i class="layui-icon layui-icon-file-b" style="color: #009688;" title="附件"></i></span>'}
</div>
<div class="flex-fill"></div>
<div class="mx-1">
<a href="{article:link /}" class="text-muted">阅读全文</a>
</div>
</div>
</div>
</div>
</article>
{/article:list}
</section>
<nav class="navigation pagination" role="navigation" aria-label="Posts Navigation">
<div class="nav-links" style="padding-bottom: 10px;" id="pages">
<ul class="page-navigator">
<li class='current'><span aria-current="page">1</span></li>
<li id="loadmore"><a style="margin-right: 0px;">当前第 1 页</a></li>
</ul>
</div>
</nav>
</div>
<div class="sidebar layui-col-md4 d-none d-lg-block">
<div class="theiaStickySidebar">
<!--博客列表广告赞助位-->
{:hook('ads_blog_cate_rimg')}
<dl class="function" id="rongkeji_remenwenzhang">
<dt class="function_t">热门文章</dt>
<dd class="function_c">
<ul>
{volist name="artHot" id="vo"}
<li style="display: block;">
<div class="list-body fanpian">
<a href="{$Request.domain}{$vo.url}" target="_blank">{$vo.title}</a>
</div>
<div class="list-footer">
<div class="text-muted text-xs"><time class="d-inline-block">{$vo.create_time|date='Y-m-d'}</time></div>
</div>
</li>
{/volist}
</ul>
</dd>
</dl>
<!--博客列表友情链接-->
{:hook('ads_blog_cate_flink')}
</div>
</div>
</div>
</div>
</main>
{include file="public/menu" /}
{/block}
{block name="script"}
<script type='text/javascript' src="{$Request.domain}/view/common/blog/js/theme.js"></script>
<script>
layui.use(['laypage'], function(){
var laypage = layui.laypage;
//执行一个laypage实例
laypage.render({
elem: 'pages' //注意,这里的 test1 是 ID不用加 # 号
,count: "{$artList['total']}" //数据总数,从服务端得到
,limit: "{$artList['per_page']}"
,curr : "{$artList['current_page']}"
//获取起始页
,jump: function(obj, first){
//首次不执行
if(!first){
var page = obj.curr;
location.href ="{$path}/"+page+'.html';
}
}
})
});
</script>
{/block}

View File

@ -0,0 +1,520 @@
{extend name="public/base" /}
{block name="title"}{$article.title} - {$sysInfo.webname}{/block}
{block name="keywords"}{$article.keywords ?: $article.title}{/block}
{block name="description"}{$article.title},{$article.description}{/block}
{block name="ogtitle"}<meta property="og:title" content="{article:title} - {$sysInfo.webname}">{/block}
{block name="ogdescription"}<meta property="og:description" content="{article:title},{$article.description ?? ''}" />{/block}
{block name="ogimage"}<meta property="og:image" content="{:getOnepic($article.content)}"/>{/block}
{block name="meta"}
<!-- SEO优化 -->
<meta property="og:type" content="article"/>
<meta property="bytedance:published_time" content="{$article.create_time|date='c'}" />
<meta property="bytedance:updated_time" content="{$article.update_time|date='c'}" />
<meta property="og:updated_time" content="{$article.update_time|date='c'}" />
<meta name="mobile-agent" content="format=html5;url={$Request.domain}{$Request.url}">
{/block}
{block name="link"}
<!-- 谷歌JavaScript结构化 -->
<script type="application/ld+json">{"@context": "https://schema.org","@type": "NewsArticle","headline": "{$article.title}","image" : "{:getOnepic($article.content)}","datePublished" : "{$article.create_time|date='c'}","dateModified": "{$article.update_time|date='c'}","author" : {"@type" : "Person","name" : "用户投稿","url": "{$Request.domain}"}},</script>
<!-- 百度JavaScript结构化 -->
<script type="application/ld+json">{"@context": "https://ziyuan.baidu.com/contexts/cambrian.jsonld","@id": "{$Request.domain}{$Request.url}","title": "{$article.title}","images": ["{:getOnepic($article.content)}"],"description": "{$article.description ?? ''}","pubDate": "{$article.create_time|date='c'}","upDate": "{$article.update_time|date='c'}"}</script>
<!-- 特效丶样式 -->
<link rel="stylesheet" href="{$Request.domain}/view/common/blog/css/style.css" type="text/css" charset="utf-8"/>
<script type='text/javascript' src="/static/jquery-3.6.0.min.js"></script>
<script type='text/javascript' src="{$Request.domain}/view/common/blog/js/view-image.min.js"></script>
<script>window.ViewImage && ViewImage.init('.post-content img');</script>
{/block}
{block name="column"}<div class="layui-hide-xs">{include file="/public/column" /}</div>{/block}
<!-- 内容 -->
{block name="content"}
<main class="py-2 py-md-2 pb-3">
<div class="layui-container">
<div class="layui-row layui-col-space15">
<div class="layui-col-md8" itemscope itemType="">
<div class="post card">
<section class="card-body">
<div class="post-header border-bottom mb-4 pb-4">
<h1 class="h3 mb-3" itemprop="headline">{article:title /}</h1>
<div class="meta d-flex align-items-center text-xs text-muted">
<div class="d-inline-block" itemprop="author" itemscope="" itemtype="">
<a href="{$Request.domain}" target="_blank" class="text-muted" itemprop="url"><span itemprop="name">{article:auther}</span></a>
<a href="{article:cate name='link'}" target="_blank" class="text-muted" rel="category">{article:cate name="name"}</a>
<time class="d-inline-block" datetime="{$article.create_time|date='Y-m-d h:m:s'}" itemprop="datePublished">{article:uptime}</time>
</div>
<div class="ml-auto text-sm yincang">
<span class="mx-1"><small>阅读 {article:pv /} 次</small></span>
</div>
</div>
<div class="border-theme bg-primary"></div>
</div>
{:hook('taoplayerdiv')}
<article class="post-content detail-body" itemprop="articleBody" view-image>
{article:content}
</article>
<!-- 文章末尾 -->
{notempty name="$article.upzip"}
{if (session('?user_name'))}
<button type="button" class="layui-btn layui-btn-xs" id="zip-download"><i class="layui-icon layui-icon-download-circle"></i>{:lang('download files')}: {$article.downloads}次</button>
{/if}
{/notempty}
<!-- 解密文件 -->
{empty name="passJieMi"}
{if($article.read_type == 1)}
<div id="jiemi" style="text-align:center">
<button type="button" class="layui-btn layui-btn-primary"><i class="layui-icon layui-icon-password" style="font-size: 30px; color: #FF5722;"></i> 阅读请解密 </button>
</div>
{/if}
{/empty}
<!-- 标签 -->
{notempty name="tags"}
<div style="margin-top: 15px">标签
{volist name="tags" id="vo" }
<a href="{$vo.url}"><span class="layui-btn layui-btn-xs layui-btn-normal layui-btn-radius">{$vo.name}</span></a>
{/volist}
</div>
{/notempty}
<div style="margin: 20px 0px 15px 0px; color: rgb(130, 125, 125);">
<p style="line-height:200%;">{$sysInfo.state|raw}</p>
</div>
<div style="margin-top: 20px;">
本文链接:<a href="{$Request.domain}{$Request.url}">{$Request.domain}{$Request.url}</a>
</div>
<div class="detail-zan">
<span class="jieda-zan" type="zan" id="article-zan">点赞 <i class="iconfont icon-zan"></i> <em>{:count($userZanList)}</em></span>
{volist name="userZanList" id="vo" }
<span><img src="{$vo.userImg}"></span>
{/volist}
</div>
</section>
<div class="card-footer text-center mt-4">
<a href="javascript:" style="color: #FFF !important;" data-img="/qrcode/?text={$Request.domain}{$Request.url}&size=200" data-title="手机扫一扫继续阅读" data-desc="微信或浏览器均可" class="single-popup shangzan mr-3 text-muted text-xs">手机浏览</a>
<a href="javascript:" style="color: #FFF !important;" data-img="{:hook('qqKefu','dashang')}" data-title="赞赏支持一下站长" data-desc="微信赞赏扫码" class="single-popup shangzan text-muted text-xs">赞赏支持</a>
<div class="text-center text-muted text-xs" style="margin-top: 30px;">
"作者已被打赏 0 次"
</div>
</div>
</div>
<div class="post card block d-flex p-4">
<span class="d-inline-block text-muted mr-2 fanpian pb-2 mb-2"> # 上一篇: {$previous|raw}</span>
<span class="d-inline-block text-muted mr-2 fanpian"># 下一篇: {$next|raw}</span>
</div>
<!-- 相关文章 -->
{notempty name="relationArticle"}
<section class="list-related">
<div class="content-related card">
<div class="card-body">
<div class="mb-3">相关文章</div>
<div class="list list-dots my-n2">
{volist name="relationArticle" id="vo"}
<div class="list-item py-2">
<a href="{$Request.domain}/{$vo.url}" target="_blank" class="list-title fanpian" title="{$vo.title}" rel="bookmark">
{$vo.title}
</a>
</div>
{/volist}
</div>
</div>
</div>
</section>
{/notempty}
<!-- 评论 -->
<section class="comments">
<div class="card">
<div class="card-body pt-4">
{//评论内容}
<div class="mb-3" id="flyReply">
文章评论 <small class="font-theme text-muted">({article:comment_num})</small>
<ul class="jieda" id="jieda">
{article:comment}
<li data-id="{comment:id /}" class="jieda-daan">
<div class="detail-about detail-about-reply">
<a class="fly-avatar" href="{comment:ulink /}"><img src="{comment:uimg /}" alt="{comment:uname}"></a>
<div class="fly-detail-user">
<a href="{comment:ulink /}" class="fly-link"><cite>{comment:uname /}</cite></a>
{if condition="$article.user_id eq $comment.user_id"}
<span>({:lang('poster')})</span>
{/if}
<span>{comment:usign /}</span>
</div>
<div class="detail-hits">
<span class="post-time" data="{comment:time}"></span>{:hook('ipShow',$comment.user.city)}</span>
</div>
{//加密未解密评论不可查看}
{if ($article.read_type == 0 || (($article.read_type == 1) && $passJieMi))}
<div class="detail-body jieda-body photos">{comment:content /}</div>
<div class="jieda-reply">
{eq name="comment.delete_time" value="0"}
<span class="jieda-zan {if($comment.zan != 0)}zanok{/if}" type="zan">
<i class="iconfont icon-zan"></i><em>{comment:zan /}</em>
</span>
<span type="reply" data-pid="{comment:id /}" data-tid="{comment:uid /}"><i class="iconfont icon-svgmoban53"></i>{:lang('reply')}</span>
{//评论编辑删除采纳权限}
<div class="jieda-admin">
{if ((session('user_id') == $comment.user_id) && (getLimtTime($comment.create_time) < 2)) OR ($user.auth ?? '')}
<span type="edit" class="comment-edit" data-id="{comment:id /}">{:lang('edit')}</span>
<span type="del" class="comment-del" data-id="{comment:id /}">{:lang('delete')}</span>
{/if}
</div>
{/eq}
{// 第二层回复}
{notempty name="$comment.children"}
{volist name="$comment.children" id="vo"}
<div class="layui-clear" style="margin:10px 0; padding: 10px; border: 1px solid #f0f0f0; background: #f6f6f6">
<a style="display: inline-block;width: 50px;">
<img src="{$vo.user.user_img}" style="width: 30px; height: 30px; border-radius: 15px; object-fit: cover">
</a>
<div style="float: left;width: calc(100% - 50px);">
<div>{$vo.user.name} {$vo.create_time|date='Y-m-d H:i'}</div>
<div class="detail-body jieda-body photos">{$vo.content|raw}</div>
<div class="jieda-reply">
{eq name="vo.delete_time" value="0"}
<span class="jieda-zan {if($vo.zan != 0)}zanok{/if}" type="zan">
<i class="iconfont icon-zan"></i><em>{$vo.zan}</em>
</span>
<span type="reply" data-pid="{$vo.id}" data-tid="{$vo.user.id}"><i class="iconfont icon-svgmoban53"></i>{:lang('reply')}</span>
{//评论编辑删除采纳权限}
<div class="jieda-admin">
{if ((session('user_id') == $vo.user.id) && (getLimtTime($vo.create_time) < 2)) OR ($user.auth ?? '')}
<span type="edit" class="comment-edit" data-id="{$vo.id}">{:lang('edit')}</span>
<span type="del" class="comment-del" data-id="{$vo.id}" >{:lang('delete')}</span>
{/if}
</div>
{/eq}
</div>
</div>
</div>
{// 第三层回复}
{notempty name="$vo.children"}
{volist name="$vo.children" id="voo"}
<div class="layui-clear" style="margin:10px 0; padding: 10px; border: 1px solid #f0f0f0;">
<a style="display: inline-block; width: 50px;">
<img src="{$voo.user.user_img}" style="width: 30px; height: 30px; object-fit: cover; border-radius: 15px;">
</a>
<div style="float: left;width: calc(100% - 50px);">
<div>{$voo.user.name} 回复 {$voo.touser} {$voo.create_time|date='Y-m-d H:i'}</div>
<div class="detail-body jieda-body photos">{$voo.content|raw}</div>
<div class="jieda-reply">
{eq name="voo.delete_time" value="0"}
<span class="jieda-zan {if($voo.zan != 0)}zanok{/if}" type="zan">
<i class="iconfont icon-zan"></i><em>{$voo.zan}</em>
</span>
<span type="reply" data-pid="{$vo.id}" data-tid="{$voo.user.id}"><i class="iconfont icon-svgmoban53"></i>{:lang('reply')}</span>
{//评论编辑删除采纳权限}
<div class="jieda-admin">
{if ((session('user_id') == $voo.user.id) && (getLimtTime($voo.create_time) < 2)) OR ($user.auth ?? '')}
<span type="edit" class="comment-edit" data-id="{$voo.id}">{:lang('edit')}</span>
<span type="del" class="comment-del" data-id="{$voo.id}">{:lang('delete')}</span>
{/if}
</div>
{/eq}
</div>
</div>
</div>
{/volist}
{/notempty}
{/volist}
{/notempty}
</div>
{else /}
<div class="detail-body jieda-body photos">
<i class="layui-icon layui-icon-password" style="font-size: 24px; color: #FF5722;"></i>
解密后查看内容
</div>
{/if}
</div>
</li>
{/article:comment}
</ul>
<div style="text-align: center" id="pages"></div>
</div>
{//评论区}
{if (config('taoler.config.is_reply') == 1 ) AND ( $article.is_reply == 0 )}
<div id="commentszbpmy" style="text-align: center;">
<h5>评论已关闭!</h5>
</div>
{/if}
{if session('?user_id') AND (config('taoler.config.is_reply') == 1 ) AND ( $article.is_reply == 1 )}
<div class="comment-respond">
<form class="comment-form">
<div class="layui-form">
<div class="layui-form-item layui-form-text">
<a name="comment"></a>
<div class="comment-textarea mb-3">
<textarea id="L_content" name="content" required lay-verify="required" placeholder="{:lang('please input the content')}" class="layui-textarea taonyeditor" style="height: 100px"></textarea>
</div>
</div>
<div class="layui-form-item que-comments">
<input type="hidden" name="article_id" value="{$article.id}" />
<input type="hidden" name="user_id" value="{:session('user_id')}" />
<button class="layui-btn layui-btn-danger" lay-filter="user-comment" lay-submit>{:lang('submit comments')}</button>
</div>
</div>
</form>
</div>
{/if}
</div>
</div>
</section>
</div>
<div class="sidebar layui-col-md4 d-none d-lg-block">
<div class="theiaStickySidebar">
{//广告}
<!--博客详情广告赞助位-->
{:hook('ads_blog_detail_rimg')}
<!-- 联系方式 -->
{:hook('callme_show', ['id' => $article.id, 'uid' => $article.user.id])}
{//热门文章}
<dl class="function" id="rongkeji_remenwenzhang">
<dt class="function_t">热门文章</dt>
<dd class="function_c">
<ul>
{volist name="artHot" id="vo"}
<li style="display: block;">
<div class="list-body fanpian">
<a href="{$vo.url}" target="_blank">{$vo.title}</a>
</div>
<div class="list-footer">
<div class="text-muted text-xs"><time class="d-inline-block">{$vo.create_time|date='Y-m-d'}</time></div>
</div>
</li>
{/volist}
</ul>
</dd>
</dl>
{//标签}
{if count($hotTag) > 0}
<dl class="function" id="rongkeji_retags">
<dt class="function_t">热门标签</dt>
<dd class="function_c">
<ul>
{volist name="hotTag" id="vo"}
<li><a href="{$vo.url}" rel="tag">{$vo.name}</a></li>
{/volist}
</ul>
</dd>
</dl>
{/if}
{//友情链接}
<!--博客详情友链-->
{:hook('ads_blog_detail_flink')}
</div>
</div>
</div>
</div>
{//crud管理模块}
{include file="/public/crud" /}
</main>
{include file="public/menu" /}
{/block}
{block name="script"}
<script type='text/javascript' src="{$Request.domain}/view/common/blog/js/theme.js"></script>
<script>
var collectionFind = "{:url('Collection/find')}",
collection = "{:url('collection/')}",
articleJieset = "{:url('Article/jieset')}",
articleDelete = "{:url('Article/delete')}",
commentJiedaZan = "{:url('Comment/jiedaZan')}",
commentJiedaCai = "{:url('Comment/jiedaCai')}",
commentGetDa = "{:url('Comment/getDa')}",
commentUpdateDa = "{:url('Comment/updateDa')}",
commentJiedaDelete = "{:url('Comment/jiedaDelete')}",
langCollection = "{:lang('collection')}",
langCancelCollection = "{:lang('cancel collection')}";
let taonystatus = "{:hook('taonystatus') ? 1 : 0} ";
layui.use(['laypage'], function(){
var $ = layui.jquery
,form = layui.form
,laypage = layui.laypage;
let uid = layui.cache.user.uid;
let id = "{$article.id}";
let LOGIN_URL = "{:url('login/index')}";
//文章点赞
$("#article-zan").on('click',function(){
//判断登陆
if(uid == -1){
layer.msg('请登录再点赞', {icon: 6}, function(){location.href = LOGIN_URL})
return false;
}
$.post("{:url('article/userZanArticle')}",{article_id:id,type:1},function(data){
if(data.code == 0){
layer.msg(data.msg,{icon:6,time:2000},function () {location.reload(true)});
} else {
layer.msg(data.msg,{icon:6,adim:6});
}
})
});
// 评论
form.on('submit(user-comment)',function (data){
comment(data.field);
});
// 提交回复
form.on('submit(submit-user-comment)', function(data){
comment(data.field);
return false;
})
// 编辑评论
$(".comment-edit").on('click', function () {
var id = $(this).data('id');
layer.open({
type: 2,
title: '修改',
shade: 0.1,
area: ['600px', '500px'],
content: "{:url('comment/edit')}" + '?id=' + id
});
});
// 删除评论
$(".comment-del").on('click', function () {
var id = $(this).data('id');
layer.confirm('需要删除吗?', {icon: 3}, function (){
$.post("{:url('comment/jiedaDelete')}", {id: id}, function (res) {
if (res.status === 0) {
toast.success({title: "成功消息", message: res.msg});
location.reload(true);
} else {
toast.error({title: "失败消息", message: res.msg});
}
})
})
});
// 评论接口
function comment(data){
if (uid == -1) {
layer.msg('请先登陆',{icon:5,time:2000},function(){location.href = LOGIN_URL});
return false;
}
var index = layer.load(1);
$.ajax({
type: "post",
url: "{:url('article/comment')}",
data: data,
dataType: "json",
success:function (res) {
layer.close(index);
if (res.code === 0) {
layer.msg(res.msg,{icon:6,time:2000},function () {location.reload(true)});
}else {
layer.open({title:'评论失败',content:res.msg,icon:5,anim:6});
}
}
});
}
// 回复用户
$("span[type='reply']").on('click',function (){
var pid = $(this).attr('data-pid');
var tid = $(this).data('tid');
var html =
'<form class="layui-form user-comment" style="margin-left:50px;">' +
'<div>' +
'<input type="hidden" name="article_id" value="{$article.id}">' +
'<input name="pid" value="'+ pid +'" class="layui-hide">' +
'<input name="to_user_id" value="'+ tid +'" class="layui-hide">' +
'<textarea name="content" required lay-verify="required" class="layui-textarea taonyeditor" style="height: 100px; right: 5px; margin: 10px 5px;"></textarea>' +
'<button type="submit" class="layui-btn" lay-submit lay-filter="submit-user-comment">提交</button>' +
'</div>' +
'</form>';
var forms = $(this).nextAll('form');
if(forms.length == 0) {
// 移除其它评论块
$('.user-comment').remove();
//动态添加评论块
$(this).next().after(html);
}
})
//解密
$("#jiemi").click(function (){
//判断登陆
if(uid == -1){
layer.msg('请先登录再查看', {icon: 6}, function(){location.href = LOGIN_URL})
return false;
}
var id = "{$article.id}";
layer.prompt(function(value, index, elem){
$.post("{:url('article/jiemi')}",{id:id, art_pass:value},function (res){
layer.close(index);
if(res.code === 0){
layer.msg(res.msg,{icon:6,time:2000},function () {
parent.location.reload(); //刷新父页面注意一定要在关闭当前iframe层之前执行刷新
});
} else {
layer.msg(res.msg,{icon:5,adim:6});
}
});
});
});
//下载
$('#zip-download').click(function (){
var id = "{$article.id}";
$.ajax({
type:"post",
url:"{:url('article/download')}",
data:{id:id},
success:function (data) {
location.href = "{:url('article/download',['id'=>$article.id])}";
}
});
});
// 评论分页
laypage.render({
elem: "pages", //注意,这里的 test1 是 ID不用加 # 号
count: "{$article.comments_count}", //数据总数,从服务端得到
limit: 10,
curr: "{$page}",
//获取起始页
jump: function (obj, first) {
var page = obj.curr;
var limit = obj.limit;
var url = "{:url('article_detail',['id' => $article.id ,'ename' =>$article['cate']['ename']])}";
var id = "{$article.id}";
//首次不执行
if (!first) {
$.post("{:url('article/detail')}", { id: id, page: page }, function () {
location.href = url + '?page=' + page + '#flyReply';
});
}
},
});
});
</script>
<!-- 插件hook位 -->
{:hook('addonhook_detail_js')}
{/block}

View File

@ -66,9 +66,9 @@
{include file="/public/crud" /} {include file="/public/crud" /}
</div> </div>
<!--底部栏--> <!--底部栏-->
<div class="site-tree-mobile-detail-bottom layui-hide-md"> <!-- <div class="site-tree-mobile-detail-bottom layui-hide-md">
<div id="LAY_jieAdmin1" data-id="{$article['id']}"></div> <div id="LAY_jieAdmin1" data-id="{$article['id']}"></div>
</div> </div> -->
</div> </div>
{include file="public/menu" /} {include file="public/menu" /}