['except' => ['cate','detail','download'] ],
];
//文章分类
public function cate()
{
$cate = new Cate();
$ad = new Slider();
$article = new ArticleModel();
//动态参数
$ename = Request::param('ename');
$type = Request::param('type','all');
$page = Request::param('page',1);
// 分类信息
$cateInfo = $cate->getCateInfo($ename);
//分页url
$url = url('cate_page',['ename'=>$ename,'type'=>$type,'page'=>$page]);
//返回最后/前面的字符串
$path = substr($url,0,strrpos($url,"/"));
//分类列表
$artList = $article->getCateList($ename,$type,$page);
// 热议文章
$artHot = $article->getArtHot(10);
//分类图片
$ad_cateImg = $ad->getSliderList(3);
//分类钻展赞助
$ad_comm = $ad->getSliderList(6);
$assignArr = [
'ename'=>$ename,
'cateinfo'=> $cateInfo,
'type'=>$type,
'artList'=>$artList,
'artHot'=>$artHot,
'ad_cateImg'=>$ad_cateImg,
'ad_comm'=>$ad_comm,
'path'=>$path,
'jspage'=>'jie'
];
View::assign($assignArr);
$cateView = is_null($cateInfo) ? 'article/cate' : 'article/' . $cateInfo->detpl . '/cate';
return View::fetch($cateView);
}
//文章详情页
public function detail()
{
$id = input('id');
$page = input('page',1);
//输出内容
$article = new ArticleModel();
$artDetail = $article->getArtDetail($id);
if(is_null($artDetail)){
// 抛出 HTTP 异常
throw new \think\exception\HttpException(404, '无内容');
}
//用户个人tag标签
$userTags = $article->where(['user_id'=>$artDetail['user_id'],'status'=>1])->where('keywords','<>','')->column('keywords');
//转换为字符串
$tagStr = implode(",",$userTags);
//转换为数组并去重
$tagArr = array_unique(explode(",",$tagStr));
$userTagCount = count($tagArr);
//赞列表
$userZanList = [];
$userZan = UserZan::where(['article_id'=>$id,'type'=>1])->select();
if(count($userZan)) {
foreach($userZan as $v){
$userZanList[] = ['userImg'=>$v->user->user_img,'name'=>$v->user->name];
}
}
// 设置内容的tag内链
$artDetail['content'] = $this->setArtTagLink($artDetail['content']);
// 标签
$tags = [];
$relationArticle = [];
$artTags = Db::name('taglist')->where('article_id',$id)->select();
if(count($artTags)) {
foreach($artTags as $v) {
$tag = Db::name('tag')->find($v['tag_id']);
if(!is_null($tag))
$tags[] = ['name'=>$tag['name'],'url'=> (string) url('tag_list',['ename'=>$tag['ename']])];
}
//相关帖子
$relationArticle = $article->getRelationTags($artTags[0]['tag_id'],$id,5);
}
$tpl = Db::name('cate')->where('id', $artDetail['cate_id'])->value('detpl');
$download = $artDetail['upzip'] ? download($artDetail['upzip'],'file') : '';
//浏览pv
Db::name('article')->where('id',$id)->inc('pv')->update();
$pv = Db::name('article')->field('pv')->where('id',$id)->value('pv');
//上一篇下一篇
$upDownArt = $article->getPrevNextArticle($id,$artDetail['cate_id']);
if(empty($upDownArt['previous'][0])) {
$previous = '前面已经没有了!';
} else {
$previous = '' . $upDownArt['previous'][0]['title'] . '';
}
if(empty($upDownArt['next'][0])) {
$next = '已经是最新的内容了!';
} else {
$next = '' . $upDownArt['next'][0]['title'] . '';
}
//评论
$comments = $this->getComments($id, $page);
//halt($comments);
//最新评论时间
$lrDate_time = Db::name('comment')->where('article_id', $id)->max('update_time',false) ?? time();
// 热议文章
$artHot = $article->getArtHot(10);
//广告
$ad = new Slider();
//分类图片
$ad_artImg = $ad->getSliderList(4);
//分类钻展赞助
$ad_comm = $ad->getSliderList(7);
//push
$push_js = Db::name('push_jscode')->where(['delete_time'=>0,'type'=>1])->cache(true)->select();
View::assign([
'article' => $artDetail,
'pv' => $pv,
'artHot' => $artHot,
'ad_art' => $ad_artImg,
'ad_comm' => $ad_comm,
'tags' => $tags,
'relationArticle' => $relationArticle,
'previous' => $previous,
'next' => $next,
'page' => $page,
'comments' => $comments,
'push_js' => $push_js,
'cid' => $id,
'lrDate_time' => $lrDate_time,
'userZanList' => $userZanList,
'userTagCount'=> $userTagCount,
'jspage' => 'jie',
$download,
]);
return View::fetch('article/'.$tpl.'/detail');
}
//评论内容
public function getComments($id, $page)
{
$comment = new Comment;
return $comment->getComment($id, $page);
}
//文章评论
public function comment()
{
// 检验发帖是否开放
if(config('taoler.config.is_reply') == 0 ) return json(['code'=>-1,'msg'=>'抱歉,系统维护中,暂时禁止评论!']);
if (Request::isAjax()){
//获取评论
$data = Request::only(['content','article_id','user_id']);
$sendId = $data['user_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){
return json(['code'=>-1, 'msg'=>'评论不可用状态']);
}
if(empty($data['content'])){
return json(['code'=>-1, 'msg'=>'评论不能为空!']);
}
$superAdmin = Db::name('user')->where('id',$sendId)->value('auth');
$data['status'] = $superAdmin ? 1 : Config::get('taoler.config.commnets_check');
$msg = $data['status'] ? '留言成功' : '留言成功,请等待审核';
//用户留言存入数据库
if (Comment::create($data)) {
//站内信
$article = Db::name('article')->field('id,title,user_id,cate_id')->where('id',$data['article_id'])->find();
// 获取分类ename,appname
$cateName = Db::name('cate')->field('ename,appname')->find($article['cate_id']);
//$link = (string) url('article_detail',['id'=>$data['article_id']]);
$link = $this->getRouteUrl($data['article_id'], $cateName['ename'], $cateName['appname']);
//评论中回复@user comment
$preg = "/@([^@\s]*)\s/";
preg_match($preg,$data['content'],$username);
if(isset($username[1])){
$receveId = Db::name('user')->whereOr('nickname', $username[1])->whereOr('name', $username[1])->value('id');
} else {
$receveId = $article['user_id'];
}
$data = ['title' => $article['title'], 'content' => '评论通知', 'link' => $link, 'user_id' => $sendId, 'type' => 2]; //type=2为评论留言
Message::sendMsg($sendId, $receveId, $data);
if(Config::get('taoler.config.email_notice')) hook('mailtohook',[$this->showUser(1)['email'],'评论审核通知','Hi亲爱的管理员:用户'.$this->showUser($this->uid)['name'].'刚刚对 ' . $article['title'] . ' 发表了评论,请尽快处理。']);
$res = ['code'=>0, 'msg'=>$msg];
} else {
$res = ['code'=>-1, 'msg'=>'留言失败'];
}
return json($res);
}
}
/**
* 添加帖子文章
* @return string|\think\Response|\think\response\Json|void
*/
public function add()
{
if (Request::isAjax()) {
// 检验发帖是否开放
if(config('taoler.config.is_post') == 0 ) return json(['code'=>-1,'msg'=>'抱歉,系统维护中,暂时禁止发帖!']);
// 数据
$data = Request::only(['cate_id', 'title', 'title_color', 'content', 'upzip', 'keywords', 'description', 'captcha']);
$data['user_id'] = $this->uid;
$tagId = input('tagid');
// 验证码
if(Config::get('taoler.config.post_captcha') == 1) {
if(!captcha_check($data['captcha'])){
return json(['code'=>-1,'msg'=> '验证码失败']);
};
}
// 验证器
$validate = new \app\common\validate\Article;
$result = $validate->scene('Artadd')->check($data);
if (true !== $result) {
return Msgres::error($validate->getError());
}
// 获取内容图片音视频标识
$iva= $this->hasIva($data['content']);
$data = array_merge($data,$iva);
// 处理内容
$data['content'] = $this->downUrlPicsReaplace($data['content']);
// 把中文,转换为英文,并去空格->转为数组->去掉空数组->再转化为带,号的字符串
$data['keywords'] = implode(',',array_filter(explode(',',trim(str_replace(',',',',$data['keywords'])))));
// 获取分类ename,appname
$cateName = Db::name('cate')->field('ename,appname')->find($data['cate_id']);
$article = new ArticleModel();
$result = $article->add($data);
if ($result['code'] == 1) {
// 获取到的最新ID
$aid = $result['data']['id'];
//写入taglist表
$tagArr = [];
if(isset($tagId)) {
$tagIdArr = explode(',',$tagId);
foreach($tagIdArr as $tid) {
$tagArr[] = ['article_id'=>$aid,'tag_id'=>$tid,'create_time'=>time()];
}
}
Db::name('taglist')->insertAll($tagArr);
// 清除文章tag缓存
Cache::tag('tagArtDetail')->clear();
// 发提醒邮件
if(Config::get('taoler.config.email_notice')) hook('mailtohook',[$this->showUser(1)['email'],'发帖审核通知','Hi亲爱的管理员:用户'.$this->showUser($this->uid)['name'].'刚刚发表了 '.$data['title'].' 新的帖子,请尽快处理。']);
$link = $this->getRouteUrl((int)$aid, $cateName['ename']);
hook('SeoBaiduPush', ['link'=>$link]); // 推送给百度收录接口
$url = $result['data']['status'] ? $link : (string)url('index/');
return Msgres::success($result['msg'], $url);
}
return Msgres::error('add_error');
}
// 子模块自定义自适应add.html模板
$cate = Db::name('cate')->field('id,detpl')->where('ename', input('cate'))->find();
// 子模块下有add.html模板
if(!empty($cate)) {
$cid = $cate['id'];
} else {
$cate['detpl'] = '';
$cid = '';
}
// 模板路径
$appName = $this->app->http->getName();
$viewRoot = root_path() . config('view.view_dir_name') . DIRECTORY_SEPARATOR . $appName . DIRECTORY_SEPARATOR;
$view = 'article' . DIRECTORY_SEPARATOR . $cate['detpl'] . DIRECTORY_SEPARATOR . 'add.html';
$vfile = $viewRoot . $view;
//子模块下存在add模板则调用,否则调用article/add.html
$addTpl = is_file($vfile) ? $vfile : 'add';
View::assign(['jspage'=>'jie','cid'=>$cid]);
return View::fetch($addTpl);
}
/**
* 编辑文章
* @param $id
* @return string|\think\Response|\think\response\Json|void
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function edit($id)
{
$article = ArticleModel::find($id);
if(Request::isAjax()){
$data = Request::only(['id','cate_id','title','title_color','user_id','content','upzip','keywords','description','captcha']);
$data['user_id'] = $this->uid;
$tagId = input('tagid');
// 验证码
if(Config::get('taoler.config.post_captcha') == 1)
{
if(!captcha_check($data['captcha'])){
return json(['code'=>-1,'msg'=> '验证码失败']);
};
}
//调用验证器
$validate = new \app\common\validate\Article();
$res = $validate->scene('Artadd')->check($data);
if(true !== $res){
return Msgres::error($validate->getError());
} else {
//获取内容图片音视频标识
$iva= $this->hasIva($data['content']);
$data = array_merge($data,$iva);
$data['content'] = $this->downUrlPicsReaplace($data['content']);
// 把,转换为,并去空格->转为数组->去掉空数组->再转化为带,号的字符串
$data['keywords'] = implode(',',array_filter(explode(',',trim(str_replace(',',',',$data['keywords'])))));
$result = $article->edit($data);
if($result == 1) {
//处理标签
$artTags = Db::name('taglist')->where('article_id',$id)->column('tag_id','id');
if(isset($tagId)) {
$tagIdArr = explode(',',$tagId);
foreach($artTags as $aid => $tid) {
if(!in_array($tid,$tagIdArr)){
//删除被取消的tag
Db::name('taglist')->delete($aid);
}
}
//查询保留的标签
$artTags = Db::name('taglist')->where('article_id',$id)->column('tag_id');
$tagArr = [];
foreach($tagIdArr as $tid) {
if(!in_array($tid, $artTags)){
//新标签
$tagArr[] = ['article_id'=>$data['id'],'tag_id'=>$tid,'create_time'=>time()];
}
}
//更新新标签
Db::name('taglist')->insertAll($tagArr);
}
//删除原有缓存显示编辑后内容
Cache::delete('article_'.$id);
$link = $this->getRouteUrl((int) $id, $article->cate->ename);
hook('SeoBaiduPush', ['link'=>$link]); // 推送给百度收录接口
return Msgres::success('edit_success',$link);
}
return Msgres::error($result);
}
}
View::assign(['article'=>$article,'jspage'=>'jie']);
// 编辑多模板支持
$tpl = Db::name('cate')->where('id', $article['cate_id'])->value('detpl');
$appName = $this->app->http->getName();
$viewRoot = root_path() . config('view.view_dir_name') . DIRECTORY_SEPARATOR . $appName . DIRECTORY_SEPARATOR;
$view = 'article' . DIRECTORY_SEPARATOR . $tpl . DIRECTORY_SEPARATOR . 'edit.html';
$vfile = $viewRoot . $view;
$editTpl = is_file($vfile) ? $vfile : 'edit';
return View::fetch($editTpl);
}
/**
* 删除
*
* @return void
*/
public function delete()
{
$article = ArticleModel::find(input('id'));
$result = $article->together(['comments'])->delete();
if($result) {
return Msgres::success('delete_success');
}
return Msgres::error('delete_error');
}
/**
* 上传接口
*
* @return void
*/
public function uploads()
{
$type = Request::param('type');
return $this->uploadFiles($type);
}
/**
* 附件下载
*
* @param [type] $id
* @return void
*/
public function download($id)
{
$zipdir = Db::name('article')->where('id',$id)->value('upzip');
$zip = substr($zipdir,1);
Db::name('article')->cache(true)->where('id',$id)->inc('downloads')->update();
//删除缓存显示下载后数据
Cache::delete('article_'.$id);
return download($zip,'my');
}
/**
* 获取描述,过滤html
*
* @return void
*/
public function getDescription()
{
$data = Request::only(['content']);
$description = getArtContent($data['content']);
return json(['code'=>0,'data'=>$description]);
}
/**
* 标题调用百度关键词词条
*
* @return void
*/
public function getWordList()
{
$title = input('title');
return $this->getBdiduSearchWordList($title);
}
/**
* 关键词
* @return \think\response\Json
*/
public function keywords()
{
$data = Request::only(['flag','keywords','content']);
$keywords = $this->setKeywords($data);
return json(['code'=>0, 'msg' => 'ok', 'data'=> $keywords]);
}
// 文章置顶、加精、评论状态
public function jieset()
{
$data = Request::param();
$article = ArticleModel::field('id,is_top,is_hot,is_reply')->find($data['id']);
switch ($data['field']){
case 'top':
if($data['rank']==1){
$article->save(['is_top' => 1]);
$res = ['status'=>0,'msg'=>'置顶成功'];
} else {
$article->save(['is_top' => 0]);
$res = ['status'=>0,'msg'=>'置顶已取消'];
}
break;
case 'hot':
if($data['rank']==1){
$article->save(['is_hot' => 1]);
$res = ['status'=>0,'msg'=>'加精成功'];
} else {
$article->save(['is_hot' => 0]);
$res = ['status'=>0,'msg'=>'加精已取消'];
}
break;
case 'reply':
if($data['rank']==1){
$article->save(['is_reply' => 1]);
$res = ['status'=>0,'msg'=>'禁评成功'];
} else {
$article->save(['is_reply' => 0]);
$res = ['status'=>0,'msg'=>'禁评已取消'];
}
}
//删除本贴设置缓存显示编辑后内容
Cache::delete('article_'.$data['id']);
//清除文章tag缓存
Cache::tag('tagArtDetail')->clear();
return json($res);
}
// 改变标题颜色
public function titleColor()
{
$data = Request::param();
$result = ArticleModel::update($data);
if($result){
//清除文章缓存
Cache::tag(['tagArt','tagArtDetail'])->clear();
$res = ['code'=> 0, 'msg'=>'标题颜色设置成功'];
}else{
$res = ['code'=> -1, 'msg'=>'标题颜色设置失败'];
}
return json($res);
}
/**
* 内容中是否有图片视频音频插入
*
* @param [type] $content
* @return boolean
*/
public function hasIva($content)
{
//判断是否插入图片
$isHasImg = strpos($content,'img[');
$data['has_img'] = is_int($isHasImg) ? 1 : 0;
//判断是否插入视频
$isHasVideo = strpos($content,'video(');
$data['has_video'] = is_int($isHasVideo) ? 1 : 0;
//判断是否插入音频
$isHasAudio = strpos($content,'audio[');
$data['has_audio'] = is_int($isHasAudio) ? 1 : 0;
return $data;
}
//设置文章内容tag
protected function setArtTagLink($content)
{
// tag链接数组
$taglink = new PushJscode();
$tag = $taglink->getAllCodes(2);
if(count($tag)) {
foreach($tag as $key=>$value) {
// 匹配所有
//$content = str_replace("$key", 'a('.$value.')['.$key.']',$content);
// 限定匹配数量 '/'.$key.'/'
// 匹配不包含[和]的内容
// $pats = '/(?)/';
//$pats = '/'.$key.'(?!<\/a>)/';
//1.不匹配 $key已经存在链接的情况
//2.或不匹配 alt="$key等等等" $key后面有"这种情况
$pats = '/' . $value['name'] . '\s?(?!<\/a>|\s?\S*")/is';
preg_match($pats,$content,$arr);
// 开启和关闭编辑器使用不同的链接方式
$rpes = hook('taonystatus') ? '' . $value['name'] . '' : 'a(' . $value['jscode'] . ')[' . $value['name'] . ']';
$content = preg_replace($pats,$rpes,$content,2);
}
}
return $content;
}
//点赞文章
public function userZanArticle()
{
//
if(Request::isPost()) {
$data = Request::post();
$data['user_id'] = $this->uid;
$userZan = Db::name('user_zan')->where(['user_id'=>$this->uid,'article_id'=>$data['article_id']])->find();
if($userZan){
return json(['code'=> -1, 'msg'=>'您已赞过了哦']);
}
$res = Db::name('user_zan')->insert($data);
if($res) {
return json(['code'=> 0, 'msg'=>'点赞成功']);
}
}
}
public function getCateTree()
{
//
$cate = Db::name('cate')->order(['id' => 'ASC','sort' => 'ASC'])->where(['delete_time'=>0])->select()->toArray();
$cateTree = array2tree($cate);
$count = count($cateTree);
$tree = [];
if($cateTree){
$tree = ['code'=>0,'msg'=>'','count'=>$count];
$res = []; //auth_rule储存数据表中的表结构
foreach($cateTree as $k => $v){
//第一层子权限
$children = [];
if(isset($v['children'])){
foreach($v['children'] as $m => $j){
//第二层子权限
$chichi = [];
if(isset($j['children'])){
//第三层子权限
foreach($j as $s){
if(isset($s['children'])){
$chichi[] = ['id'=>$s['id'],'catename'=>$s['catename'],'pid'=>$s['pid']]; //子数据的子数据
}
}
}
//if($j['level'] < 3){}
$children[] = ['id'=>$j['id'],'catename'=>$j['catename'],'pid'=>$j['pid'],'children'=>$chichi]; //子数据
}
}
$data[] = ['id'=>$v['id'],'catename'=>$v['catename'],'pid'=>$v['pid'],'children'=>$children];
}
//构造一个顶级菜单pid=0的数组。把权限放入顶级菜单下子权限中
//$tree['data'][] = ['id'=>0,'catename'=>'顶级','pid'=>0,'children'=>$data];
$tree['data'] = $data;
}
return json($tree);
}
}