|
|
@@ -5,35 +5,40 @@ namespace App\Services;
|
|
|
|
|
|
|
|
|
use App\Menu;
|
|
|
-use App\User;
|
|
|
use App\UserVisitMenuLog;
|
|
|
+use Illuminate\Database\Eloquent\Builder;
|
|
|
+use Illuminate\Database\Eloquent\Model;
|
|
|
use Illuminate\Http\Request;
|
|
|
-use Illuminate\Support\Arr;
|
|
|
+use Illuminate\Support\Collection;
|
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
use Illuminate\Support\Facades\Redis;
|
|
|
|
|
|
class CheckActiveMenuService
|
|
|
{
|
|
|
+ /**
|
|
|
+ *同步数据到数据库并且将L1转移到L2
|
|
|
+ */
|
|
|
public static function sync()
|
|
|
+
|
|
|
{
|
|
|
try {
|
|
|
- $userVisitMenuLogsL1 = Redis::LRANGE('UserVisitMenuLogsL1', 0, -1);
|
|
|
- UserVisitMenuLog::query()->insert(self::redisListToArray($userVisitMenuLogsL1));
|
|
|
+ self::syncToDB();
|
|
|
self::switchL1ToL2();
|
|
|
} catch (\Exception $e) {
|
|
|
+ // TODO 同步异常的处理策略
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * 将用户菜单点击事件保存
|
|
|
* @param Request $request
|
|
|
*/
|
|
|
public static function set(Request $request): void
|
|
|
{
|
|
|
- $uri = substr($request->getRequestUri(), 1);
|
|
|
// 请求方法为get
|
|
|
if ($request->method() == 'GET') {
|
|
|
- $menu = Menu::query()->where('route', $uri)->first();
|
|
|
+ $menu = Menu::query()->where('route', substr($request->getRequestUri(), 1))->first();
|
|
|
if ($menu) {
|
|
|
//redis正常保存在缓存中
|
|
|
$date = date('Y-m-d H:i:s');
|
|
|
@@ -47,35 +52,31 @@ class CheckActiveMenuService
|
|
|
//菜单点击入缓存
|
|
|
Redis::LPUSH('UserVisitMenuLogsL1', $userVisitMenuLog);
|
|
|
} catch (\Exception $e) {
|
|
|
- //连接不上缓存。直接入库
|
|
|
+ // TODO 缓存异常的处理策略
|
|
|
+ }finally{
|
|
|
$userVisitMenuLog->save();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取活跃菜单
|
|
|
+ * @return Builder|Builder[]|\Illuminate\Database\Eloquent\Collection|Model|null
|
|
|
+ */
|
|
|
public static function activeMenus()
|
|
|
{
|
|
|
- if (Redis::LLEN('UserVisitMenuLogsL1') + Redis::LLEN('UserVisitMenuLogsL2') > 0) {
|
|
|
- //缓存中有数据
|
|
|
-
|
|
|
- $array1 = self::redisListToArray(Redis::LRANGE('UserVisitMenuLogsL1', 0, -1));
|
|
|
- $array2 = self::redisListToArray(Redis::LRANGE('UserVisitMenuLogsL2', 0, -1));
|
|
|
- $array = array_merge($array1, $array2);
|
|
|
- $conller = collect($array);
|
|
|
- $user_id = 1;
|
|
|
- if (Auth::user()) {
|
|
|
- $user_id = Auth::user()->id;
|
|
|
+ $user_id = self::getUserId();
|
|
|
+ try {
|
|
|
+ Redis::LLEN('UserVisitMenuLogsL1');
|
|
|
+ if (Redis::LLEN('UserVisitMenuLogsL1') + Redis::LLEN('UserVisitMenuLogsL2') > 0) {
|
|
|
+ //缓存中有数据
|
|
|
+ return self::getFromRedis($user_id);
|
|
|
}
|
|
|
- $arr = $conller->filter(function ($item) use ($user_id){
|
|
|
- return $user_id === $item['user_id'];
|
|
|
- })->groupBy('menu_id')->sortByDesc(function ($item){
|
|
|
- return $item->count();
|
|
|
- })->forPage(0,5)->keys();
|
|
|
- $menus = Menu::query()->find($arr)->sortBy(function($item)use($arr){
|
|
|
- return $arr->search($item->id);
|
|
|
- });
|
|
|
- dd($menus,$arr);
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // TODO 缓存异常的处理策略
|
|
|
+ } finally {
|
|
|
+ return self::getFromDB($user_id);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -108,4 +109,100 @@ class CheckActiveMenuService
|
|
|
Redis::LPUSH('UserVisitMenuLogsL2', Redis::LPOP('UserVisitMenuLogsL1'));
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ public static function getUserId(): int
|
|
|
+ {
|
|
|
+ $user_id = 1;
|
|
|
+ if (Auth::user()) {
|
|
|
+ $user_id = Auth::user()->id;
|
|
|
+ }
|
|
|
+ return $user_id;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从数据库获取活跃菜单
|
|
|
+ * @param $user_id
|
|
|
+ * @return Builder|Builder[]|\Illuminate\Database\Eloquent\Collection|Model|null
|
|
|
+ */
|
|
|
+ public static function getFromDB($user_id)
|
|
|
+ {
|
|
|
+ return self::getMenusAndSort(self::getMenuIdsFromDB($user_id));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从缓存获取活跃菜单
|
|
|
+ * @param $user_id
|
|
|
+ * @return Builder|Builder[]|\Illuminate\Database\Eloquent\Collection|Model|null
|
|
|
+ */
|
|
|
+ public static function getFromRedis($user_id)
|
|
|
+ {
|
|
|
+ return self::getMenusAndSort(self::getMenuIdsFromRedis($user_id));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取活跃菜单并按照活跃度排序
|
|
|
+ * @param Collection $arr
|
|
|
+ * @return Builder|Builder[]|\Illuminate\Database\Eloquent\Collection|Model|null
|
|
|
+ */
|
|
|
+ public static function getMenusAndSort(Collection $arr)
|
|
|
+ {
|
|
|
+ return Menu::query()
|
|
|
+ ->find($arr)
|
|
|
+ //根据菜单Id查询
|
|
|
+ ->sortBy(function ($item) use ($arr) {
|
|
|
+ return $arr->search($item->id);
|
|
|
+ //将查询结果按照上面拍好的顺序重新排列
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param $user_id
|
|
|
+ * @return Collection|\Tightenco\Collect\Support\Collection
|
|
|
+ */
|
|
|
+ public static function getMenuIdsFromRedis($user_id)
|
|
|
+ {
|
|
|
+ return collect(array_merge(self::redisListToArray(Redis::LRANGE('UserVisitMenuLogsL1', 0, -1)), self::redisListToArray(Redis::LRANGE('UserVisitMenuLogsL2', 0, -1))))
|
|
|
+ //从缓存中查找全部用户的活跃菜单数据,合并L1,L2
|
|
|
+ ->filter(function ($item) use ($user_id) {
|
|
|
+ return $user_id === $item['user_id'];
|
|
|
+ })
|
|
|
+ //根据user_id筛选
|
|
|
+ ->groupBy('menu_id')
|
|
|
+ //根据menu_id分组
|
|
|
+ ->sortByDesc(function ($item) {
|
|
|
+ return $item->count();
|
|
|
+ })
|
|
|
+ //根据分组结果的二级列表降序排列
|
|
|
+ ->forPage(0, 5)
|
|
|
+ //取前数量最高的五条
|
|
|
+ ->keys();
|
|
|
+ //只获取对应的菜单Id
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param $user_id
|
|
|
+ * @return Builder[]|\Illuminate\Database\Eloquent\Collection|Collection
|
|
|
+ */
|
|
|
+ public static function getMenuIdsFromDB($user_id)
|
|
|
+ {
|
|
|
+ return UserVisitMenuLog::query()
|
|
|
+ ->selectRaw('id')
|
|
|
+ ->where('user_id', $user_id)
|
|
|
+ ->groupBy('menu_id')
|
|
|
+ ->get()->sortByDesc(function ($item) {
|
|
|
+ return $item->count();
|
|
|
+ })
|
|
|
+ ->forPage(0, 5)
|
|
|
+ ->map(function ($item) {
|
|
|
+ return $item->id;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public static function syncToDB(): void
|
|
|
+ {
|
|
|
+ UserVisitMenuLog::query()->insert(self::redisListToArray(Redis::LRANGE('UserVisitMenuLogsL1', 0, -1)));
|
|
|
+ }
|
|
|
}
|