UserBehaviorLogModel.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <?php
  2. declare (strict_types = 1);
  3. namespace app\model;
  4. use think\Model;
  5. /**
  6. * 用户操作日志模型
  7. */
  8. class UserBehaviorLogModel extends Model
  9. {
  10. // 设置表名
  11. protected $table = 'merchant_user_behavior_log';
  12. // 设置主键
  13. protected $pk = 'id';
  14. // 操作状态常量
  15. const STATUS_FAILED = 0; // 操作失败
  16. const STATUS_SUCCESS = 1; // 操作成功
  17. /**
  18. * 记录操作日志
  19. * @param array $data 日志数据
  20. * @return bool
  21. */
  22. public static function recordBehavior(array $data): bool
  23. {
  24. try {
  25. $log = new self();
  26. $log->merchant_id = $data['merchant_id'] ?? 0;
  27. $log->user_id = $data['user_id'] ?? 0;
  28. $log->behavior = $data['behavior'] ?? '';
  29. $log->behavior_desc = $data['behavior_desc'] ?? '';
  30. $log->behavior_ip = $data['behavior_ip'] ?? '';
  31. $log->behavior_url = $data['behavior_url'] ?? '';
  32. $log->create_time = time();
  33. $log->behavior_status = $data['behavior_status'] ?? self::STATUS_SUCCESS;
  34. return $log->save();
  35. } catch (\Exception $e) {
  36. // 记录日志失败不影响业务流程
  37. return false;
  38. }
  39. }
  40. /**
  41. * 获取操作日志列表
  42. * @param int $merchantId 商户ID
  43. * @param int $page 页码
  44. * @param int $limit 每页数量
  45. * @param array $filters 过滤条件
  46. * @return array
  47. */
  48. public static function getBehaviorLogs(int $merchantId, int $page = 1, int $limit = 20, array $filters = []): array
  49. {
  50. $where = [
  51. ['merchant_id', '=', $merchantId]
  52. ];
  53. // 用户ID筛选
  54. if (!empty($filters['user_id'])) {
  55. $where[] = ['user_id', '=', $filters['user_id']];
  56. }
  57. // 行为类型筛选
  58. if (!empty($filters['behavior'])) {
  59. $where[] = ['behavior', '=', $filters['behavior']];
  60. }
  61. // 操作状态筛选
  62. if (isset($filters['behavior_status']) && $filters['behavior_status'] !== '') {
  63. $where[] = ['behavior_status', '=', $filters['behavior_status']];
  64. }
  65. // IP地址筛选
  66. if (!empty($filters['behavior_ip'])) {
  67. $where[] = ['behavior_ip', 'like', '%' . $filters['behavior_ip'] . '%'];
  68. }
  69. // 时间范围筛选
  70. if (!empty($filters['start_time'])) {
  71. $where[] = ['create_time', '>=', strtotime($filters['start_time'])];
  72. }
  73. if (!empty($filters['end_time'])) {
  74. $where[] = ['create_time', '<=', strtotime($filters['end_time'])];
  75. }
  76. // 关键词搜索(在行为描述中搜索)
  77. if (!empty($filters['keyword'])) {
  78. $where[] = ['behavior_desc', 'like', '%' . $filters['keyword'] . '%'];
  79. }
  80. $query = self::where($where);
  81. $total = $query->count();
  82. $list = $query->field('id, merchant_id, user_id, behavior, behavior_desc, behavior_ip, behavior_url, create_time, behavior_status')
  83. ->order('id', 'desc')
  84. ->page($page, $limit)
  85. ->select();
  86. // 获取相关用户信息
  87. if ($list->count() > 0) {
  88. $userIds = array_unique(array_column($list->toArray(), 'user_id'));
  89. $users = UserModel::whereIn('user_id', $userIds)
  90. ->field('user_id, user_name, nick_name')
  91. ->select()
  92. ->toArray();
  93. $userMap = [];
  94. foreach ($users as $user) {
  95. $userMap[$user['user_id']] = $user;
  96. }
  97. // 添加用户信息和格式化数据
  98. foreach ($list as &$log) {
  99. $log['user_name'] = $userMap[$log['user_id']]['user_name'] ?? '';
  100. $log['nick_name'] = $userMap[$log['user_id']]['nick_name'] ?? '';
  101. $log['status_text'] = $log['behavior_status'] == self::STATUS_SUCCESS ? '成功' : '失败';
  102. }
  103. }
  104. return [
  105. 'list' => $list,
  106. 'total' => $total,
  107. 'page' => $page,
  108. 'limit' => $limit
  109. ];
  110. }
  111. /**
  112. * 获取用户最近操作记录
  113. * @param int $userId 用户ID
  114. * @param int $limit 获取数量
  115. * @return array
  116. */
  117. public static function getRecentBehaviors(int $userId, int $limit = 10): array
  118. {
  119. $list = self::where('user_id', $userId)
  120. ->field('behavior, behavior_desc, behavior_ip, behavior_url, create_time, behavior_status')
  121. ->order('id', 'desc')
  122. ->limit($limit)
  123. ->select()
  124. ->toArray();
  125. // 格式化数据
  126. foreach ($list as &$log) {
  127. $log['status_text'] = $log['behavior_status'] == self::STATUS_SUCCESS ? '成功' : '失败';
  128. $log['create_time_text'] = date('Y-m-d H:i:s', $log['create_time']);
  129. // 解析请求参数
  130. try {
  131. $log['params'] = json_decode($log['behavior_desc'], true) ?: [];
  132. } catch (\Exception $e) {
  133. $log['params'] = [];
  134. }
  135. }
  136. return $list;
  137. }
  138. /**
  139. * 获取操作统计信息
  140. * @param int $merchantId 商户ID
  141. * @param int $userId 用户ID(可选)
  142. * @param string $startDate 开始日期
  143. * @param string $endDate 结束日期
  144. * @return array
  145. */
  146. public static function getBehaviorStatistics(int $merchantId, int $userId = 0, string $startDate = '', string $endDate = ''): array
  147. {
  148. $where = [
  149. ['merchant_id', '=', $merchantId]
  150. ];
  151. if ($userId > 0) {
  152. $where[] = ['user_id', '=', $userId];
  153. }
  154. if ($startDate) {
  155. $where[] = ['create_time', '>=', strtotime($startDate)];
  156. }
  157. if ($endDate) {
  158. $where[] = ['create_time', '<=', strtotime($endDate . ' 23:59:59')];
  159. }
  160. // 总操作次数
  161. $totalCount = self::where($where)->count();
  162. // 成功次数
  163. $successCount = self::where($where)
  164. ->where('behavior_status', self::STATUS_SUCCESS)
  165. ->count();
  166. // 失败次数
  167. $failedCount = self::where($where)
  168. ->where('behavior_status', self::STATUS_FAILED)
  169. ->count();
  170. // 活跃用户数
  171. $activeUsers = self::where($where)
  172. ->group('user_id')
  173. ->count();
  174. // 按行为类型统计
  175. $behaviorStats = self::where($where)
  176. ->field('behavior, count(*) as count')
  177. ->group('behavior')
  178. ->select()
  179. ->toArray();
  180. // 行为统计已经是权限配置中的描述,无需额外处理
  181. return [
  182. 'total_count' => $totalCount,
  183. 'success_count' => $successCount,
  184. 'failed_count' => $failedCount,
  185. 'success_rate' => $totalCount > 0 ? round($successCount / $totalCount * 100, 2) : 0,
  186. 'active_users' => $activeUsers,
  187. 'behavior_stats' => $behaviorStats
  188. ];
  189. }
  190. /**
  191. * 获取所有行为类型(从权限配置中获取)
  192. * @return array
  193. */
  194. public static function getAllBehaviors(): array
  195. {
  196. $behaviors = [];
  197. $permissions = config('permission.permissions');
  198. foreach ($permissions as $controller => $moduleInfo) {
  199. $module = $moduleInfo['module'] ?? $controller;
  200. foreach ($moduleInfo['actions'] ?? [] as $action => $desc) {
  201. $behaviors[] = [
  202. 'value' => $module . '-' . $desc,
  203. 'label' => $module . '-' . $desc
  204. ];
  205. }
  206. }
  207. return $behaviors;
  208. }
  209. }