活跃的用户

This commit is contained in:
fthvgb1 2018-06-02 18:21:53 +08:00
parent cffe2ec89c
commit d1e0c21a9a
10 changed files with 213 additions and 6 deletions

View File

@ -0,0 +1,44 @@
<?php
namespace App\Console\Commands;
use App\Models\User;
use Illuminate\Console\Command;
class CalculateActiveUser extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'larabbs:calculate-active-user';
/**
* The console command description.
*
* @var string
*/
protected $description = '生成活跃用户';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
* @param User $user
*/
public function handle(User $user)
{
$this->info('开始计算!');
$user->calculateAndCacheActiveUsers();
$this->info('生成成功!');
}
}

View File

@ -26,6 +26,7 @@ class Kernel extends ConsoleKernel
{
// $schedule->command('inspire')
// ->hourly();
$schedule->command('larabbs:calculate-active-user')->hourly();
}
/**

View File

@ -4,13 +4,15 @@ namespace App\Http\Controllers;
use App\Models\Category;
use App\Models\Topic;
use App\Models\User;
use Illuminate\Http\Request;
class CategoriesController extends Controller
{
public function show(Category $category, Request $request)
public function show(Category $category, Request $request, User $user)
{
$topics = Topic::where('category_id', $category->id)->withOrder($request->order)->with('user', 'category')->paginate();
return view('topics.index', compact('topics', 'category'));
$active_users = $user->getActiveUsers();
return view('topics.index', compact('topics', 'category', 'active_users'));
}
}

View File

@ -5,6 +5,7 @@ namespace App\Http\Controllers;
use App\Http\Requests\TopicRequest;
use App\Models\Category;
use App\Models\Topic;
use App\Models\User;
use App\Tools\ImageUploadTool;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@ -22,10 +23,11 @@ class TopicsController extends Controller
return view('topics.create_and_edit', compact('topic', 'categories'));
}
public function index(Request $request, Topic $topic)
public function index(Request $request, Topic $topic, User $user)
{
$active_users = $user->getActiveUsers();
$topics = $topic->with('user', 'category')->withOrder($request->order)->paginate();
return view('topics.index', compact('topics'));
return view('topics.index', compact('topics', 'active_users'));
}
public function show(Topic $topic, Request $request)

View File

@ -0,0 +1,96 @@
<?php
/**
* Created by PhpStorm.
* User: xing
* Date: 2018/6/2
* Time: 17:16
*/
namespace App\Models\Traits;
use App\Models\Reply;
use App\Models\Topic;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
trait ActiveUserHelper
{
protected $users = [];
protected $topic_weight = 4;
protected $reply_weight = 1;
protected $pass_days = 7;
protected $user_number = 6;
protected $cache_key = 'larabbs_active_users';
protected $cache_expire_in_minutes = 65;
public function getActiveUsers()
{
return Cache::remember($this->cache_key, $this->cache_expire_in_minutes, function () {
return $this->calculateActiveUsers();
});
}
public function calculateActiveUsers()
{
$this->calculateTopicScore();
$this->calculateReplyScore();
$users = array_sort($this->users, function ($user) {
return $user['score'];
});
$users = array_reverse($users, true);
$users = array_slice($users, 0, $this->user_number, true);
$active_users = collect();
foreach ($users as $user_id => $user) {
$user = $this->find($user_id);
if ($user) {
$active_users->push($user);
}
}
return $active_users;
}
private function calculateTopicScore()
{
// 从话题数据表里取出限定时间范围($pass_days有发表过话题的用户
// 并且同时取出用户此段时间内发布话题的数量
$topic_users = Topic::query()->select(\DB::raw('user_id, count(*) as topic_count'))
->where('created_at', '>=', Carbon::now()->subDays($this->pass_days))
->groupBy('user_id')
->get();
// 根据话题数量计算得分
foreach ($topic_users as $value) {
$this->users[$value->user_id]['score'] = $value->topic_count * $this->topic_weight;
}
}
protected function calculateReplyScore()
{
$reply_users = Reply::query()
->select(\DB::raw('user_id,count(*) as reply_count'))
->where('created_at', '>=', Carbon::now()->subDays($this->pass_days))
->groupBy('user_id')
->get();
foreach ($reply_users as $value) {
$reply_score = $value->reply_count * $this->reply_weight;
if (isset($this->users[$value->user_id])) {
$this->users[$value->user_id]['score'] += $reply_score;
} else {
$this->users[$value->user_id]['score'] = $reply_score;
}
}
}
public function calculateAndCacheActiveUsers()
{
$active_users = $this->calculateActiveUsers();
$this->cacheActiveUsers($active_users);
}
private function cacheActiveUsers($active_users)
{
Cache::put($this->cache_key, $active_users, $this->cache_expire_in_minutes);
}
}

View File

@ -2,6 +2,7 @@
namespace App\Models;
use App\Models\Traits\ActiveUserHelper;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Auth;
@ -13,6 +14,7 @@ class User extends Authenticatable
notify as protected laravelNotify;
}
use HasRoles;
use ActiveUserHelper;
/**
* The attributes that are mass assignable.

19
public/css/app.css vendored
View File

@ -8457,6 +8457,25 @@ body {
border-bottom: 1px solid #efefef;
}
/**
sidebar
*/
.sidebar .panel-body {
padding: 12px;
}
.sidebar hr {
margin-top: 8px;
margin-bottom: 10px;
}
.sidebar .active-users a.media {
color: #797878;
line-height: 26px;
font-size: 0.9em;
}
/* Topic Index Page */
.topics-index-page .topic-list .nav > li > a,

View File

@ -112,6 +112,28 @@ body {
}
/**
sidebar
*/
.sidebar {
.panel-body {
padding: 12px;
}
hr {
margin-top: 8px;
margin-bottom: 10px;
}
.active-users {
a.media {
color: #797878;
line-height: 26px;
font-size: 0.9em;
}
}
}
/* Topic Index Page */
.topics-index-page, .categories-show-page {
.topic-list {

View File

@ -6,3 +6,22 @@
</a>
</div>
</div>
@if(count($active_users))
<div class="panel panel-default">
<div class="panel-body active_users">
<div class="text-center">活跃用户</div>
<hr>
@foreach($active_users as $active_user)
<a class="media" href="{{route('users.show',$active_user->id)}}">
<div class="media-left media-middle">
<img src="{{$active_user->avatar}}" width="24px" height="24px" class="img-circle media-object"
alt="header">
</div>
<div class="media-body">
<span class="media-heading">{{$active_user->name}}</span>
</div>
</a>
@endforeach
</div>
</div>
@endif

View File

@ -1,6 +1,6 @@
{
"site_name": "larabbs - Powered by LaraBBS",
"contact_email": "fthvgb1@163.com",
"contact_email": "fthvgb2@163.com",
"seo_description": "laravel\u642d\u5efa\u7684bbs",
"seo_keyword": "laravel,bbs,laravel\u793e\u533a"
}