|
|
@@ -3225,4 +3225,206 @@ class UserRepository extends BaseRepository
|
|
3225
|
3225
|
$resultArray = array_diff($originalArray, [$uid]);
|
|
3226
|
3226
|
return $resultArray;
|
|
3227
|
3227
|
}
|
|
|
3228
|
+
|
|
|
3229
|
+
|
|
|
3230
|
+ /**
|
|
|
3231
|
+ * 设置用户 身份
|
|
|
3232
|
+ * @param $uid
|
|
|
3233
|
+ * @param $identityId
|
|
|
3234
|
+ * @return int|mixed|null
|
|
|
3235
|
+ * @throws DbException
|
|
|
3236
|
+ */
|
|
|
3237
|
+ public function setUserIdentity($uid, $identityId = null)
|
|
|
3238
|
+ {
|
|
|
3239
|
+ $result = null;
|
|
|
3240
|
+ if (empty($identityId)) {
|
|
|
3241
|
+ $identityId = $this->getUserIdentity($uid);
|
|
|
3242
|
+ }
|
|
|
3243
|
+ $this->dao->update($uid, ['user_group' => $identityId]);
|
|
|
3244
|
+ return $identityId;
|
|
|
3245
|
+ }
|
|
|
3246
|
+
|
|
|
3247
|
+ /**
|
|
|
3248
|
+ * 获取用户 身份
|
|
|
3249
|
+ * @param $uid
|
|
|
3250
|
+ * @return int|mixed
|
|
|
3251
|
+ * @throws DataNotFoundException
|
|
|
3252
|
+ * @throws DbException
|
|
|
3253
|
+ * @throws ModelNotFoundException
|
|
|
3254
|
+ */
|
|
|
3255
|
+ public function getUserIdentity($uid)
|
|
|
3256
|
+ {
|
|
|
3257
|
+ // 1、获取所有等级信息
|
|
|
3258
|
+ /** @var UserIdentityRepository $identityRepository */
|
|
|
3259
|
+ $identityRepository = app()->make(UserIdentityRepository::class);
|
|
|
3260
|
+ $identityList = $identityRepository->getIdentityList();
|
|
|
3261
|
+
|
|
|
3262
|
+ // 2、获取身份需要的最深等级
|
|
|
3263
|
+ $lowerLevelNumList = array_column($identityList, 'lower_level_num');
|
|
|
3264
|
+ $lowerLevelNumMax = max($lowerLevelNumList);
|
|
|
3265
|
+ $lowerLevelNumMin = min($lowerLevelNumList);
|
|
|
3266
|
+ $needLower = $lowerLevelNumMax;
|
|
|
3267
|
+ if($lowerLevelNumMin == 0) {
|
|
|
3268
|
+ $needLower = $lowerLevelNumMin;
|
|
|
3269
|
+ }
|
|
|
3270
|
+
|
|
|
3271
|
+ // 3、获取下级用户 贡献值
|
|
|
3272
|
+ $userContributionSumMap = [];
|
|
|
3273
|
+ $uidContributeList = $this->getUidContributeListBySpreadUidList([$uid]);
|
|
|
3274
|
+ foreach ($uidContributeList as $uidContribute) {
|
|
|
3275
|
+ $userContributionSumMap[$uidContribute['uid']] = $this->getContributionSumByLevel([$uidContribute['uid']], $needLower);
|
|
|
3276
|
+ $userContributionSumMap[$uidContribute['uid']][0] = $uidContribute['contribute'];
|
|
|
3277
|
+ }
|
|
|
3278
|
+
|
|
|
3279
|
+ // 4、获取个人贡献值
|
|
|
3280
|
+ $userData = $this->dao->get($uid)->toArray();
|
|
|
3281
|
+
|
|
|
3282
|
+ // 5、当前用户等级
|
|
|
3283
|
+ $identityId = 0;
|
|
|
3284
|
+ usort($identityList, function ($a, $b) {
|
|
|
3285
|
+ return $b['user_group_id'] <=> $a['user_group_id']; // 反转顺序,倒序排列
|
|
|
3286
|
+ });
|
|
|
3287
|
+ foreach ($identityList as $item) {
|
|
|
3288
|
+ $lowerLevelNum = $item['lower_level_num']??0;
|
|
|
3289
|
+
|
|
|
3290
|
+ $arriveNumOwn = $userData['contribute'];
|
|
|
3291
|
+ $arriveNumTeam = 0;
|
|
|
3292
|
+ $subordinateContribution = [];
|
|
|
3293
|
+
|
|
|
3294
|
+ foreach ($userContributionSumMap as $key => $value) {
|
|
|
3295
|
+ $subordinateContribution[$key] = 0;
|
|
|
3296
|
+ if ($lowerLevelNum != 0) {
|
|
|
3297
|
+ foreach ($value as $k => $v) {
|
|
|
3298
|
+ if ($k <= $lowerLevelNum) {
|
|
|
3299
|
+ $subordinateContribution[$key] += $v;
|
|
|
3300
|
+ } else {
|
|
|
3301
|
+ break;
|
|
|
3302
|
+ }
|
|
|
3303
|
+ }
|
|
|
3304
|
+ } else {
|
|
|
3305
|
+ $subordinateContribution[$key] = array_sum($value);
|
|
|
3306
|
+ }
|
|
|
3307
|
+ }
|
|
|
3308
|
+ if (!empty($subordinateContribution)) {
|
|
|
3309
|
+ // 大区业绩
|
|
|
3310
|
+ $dqYj = max($subordinateContribution);
|
|
|
3311
|
+ // 总业绩
|
|
|
3312
|
+ $zYj = array_sum($subordinateContribution);
|
|
|
3313
|
+ // 小区团体业绩
|
|
|
3314
|
+ $arriveNumTeam = bcsub($zYj, $dqYj, 2);
|
|
|
3315
|
+ }
|
|
|
3316
|
+ if ($item['arrive_num_own'] <= $arriveNumOwn && $item['arrive_num_team'] <= $arriveNumTeam) {
|
|
|
3317
|
+ $identityId = $item['user_group_id'];
|
|
|
3318
|
+ break;
|
|
|
3319
|
+ }
|
|
|
3320
|
+ }
|
|
|
3321
|
+ return $identityId;
|
|
|
3322
|
+ }
|
|
|
3323
|
+
|
|
|
3324
|
+ /**
|
|
|
3325
|
+ * 获取该会员的所有下级会员
|
|
|
3326
|
+ */
|
|
|
3327
|
+ public function getUidContributeListBySpreadUidList(array $uidList)
|
|
|
3328
|
+ {
|
|
|
3329
|
+ return Db::name("user")
|
|
|
3330
|
+ ->whereIn("spread_uid", $uidList)
|
|
|
3331
|
+ ->field("uid, contribute, spread_uid")
|
|
|
3332
|
+ ->select()
|
|
|
3333
|
+ ->toArray();
|
|
|
3334
|
+ }
|
|
|
3335
|
+
|
|
|
3336
|
+ /**
|
|
|
3337
|
+ * 计算指定用户下属每一层级的总贡献值。
|
|
|
3338
|
+ *
|
|
|
3339
|
+ * @param array $initialUserIds 初始用户ID列表 (视为第0层)。
|
|
|
3340
|
+ * @param int $maxDepth 需要查询的最大深度(相对于初始列表)。
|
|
|
3341
|
+ * 0 表示查询所有层级直到末端。
|
|
|
3342
|
+ * 1 表示只计算第1层(直接下级)的总贡献。
|
|
|
3343
|
+ * N 表示计算到第 N 层(包含第N层)的总贡献。
|
|
|
3344
|
+ * @return array 返回一个数组,键是层级号(从1开始),值是该层级所有用户的贡献值总和。
|
|
|
3345
|
+ * 例如:[ 1 => 600, 2 => 1300 ]
|
|
|
3346
|
+ */
|
|
|
3347
|
+ public function getContributionSumByLevel(array $initialUserIds, int $maxDepth = 0): array
|
|
|
3348
|
+ {
|
|
|
3349
|
+ $levelContributions = []; // 结果数组 [level => total_contribution]
|
|
|
3350
|
+ if (empty($initialUserIds)) {
|
|
|
3351
|
+ return $levelContributions;
|
|
|
3352
|
+ }
|
|
|
3353
|
+
|
|
|
3354
|
+ $currentLevelIds = $initialUserIds; // 当前层级的用户ID (初始为第0层)
|
|
|
3355
|
+ $currentLevel = 0; // 当前层级号
|
|
|
3356
|
+
|
|
|
3357
|
+ // 使用一个集合跟踪所有已处理过的下级用户ID,防止重复计算和循环
|
|
|
3358
|
+ $processedSubordinateIds = [];
|
|
|
3359
|
+
|
|
|
3360
|
+ while (!empty($currentLevelIds)) {
|
|
|
3361
|
+ // 计算下一层级的编号
|
|
|
3362
|
+ $nextLevel = $currentLevel + 1;
|
|
|
3363
|
+
|
|
|
3364
|
+ // 检查是否达到最大深度限制
|
|
|
3365
|
+ if ($maxDepth > 0 && $nextLevel > $maxDepth) {
|
|
|
3366
|
+ break; // 停止查询更深的层级
|
|
|
3367
|
+ }
|
|
|
3368
|
+
|
|
|
3369
|
+ // 批量查询当前层级用户的直接下级
|
|
|
3370
|
+ // 使用 array_chunk 防止 WHERE IN 子句过长 (根据数据库限制调整 chunkSize)
|
|
|
3371
|
+ $chunkSize = 500;
|
|
|
3372
|
+ $subordinatesOfCurrentLevel = [];
|
|
|
3373
|
+ foreach(array_chunk($currentLevelIds, $chunkSize) as $chunk) {
|
|
|
3374
|
+ $subordinatesChunk = Db::name('user')
|
|
|
3375
|
+ ->field('uid, contribute') // 只需要下级的uid和贡献值
|
|
|
3376
|
+ ->whereIn('spread_uid', $chunk) // spread_uid 在当前层级用户块中
|
|
|
3377
|
+ ->select()
|
|
|
3378
|
+ ->toArray();
|
|
|
3379
|
+ $subordinatesOfCurrentLevel = array_merge($subordinatesOfCurrentLevel, $subordinatesChunk);
|
|
|
3380
|
+ }
|
|
|
3381
|
+
|
|
|
3382
|
+ // 如果没有找到任何下级,结束循环
|
|
|
3383
|
+ if (empty($subordinatesOfCurrentLevel)) {
|
|
|
3384
|
+ break;
|
|
|
3385
|
+ }
|
|
|
3386
|
+
|
|
|
3387
|
+ $nextLevelTotalContribution = 0;
|
|
|
3388
|
+ $nextLevelIds = []; // 存储下一轮需要查询的用户ID
|
|
|
3389
|
+
|
|
|
3390
|
+ // 遍历找到的所有下级
|
|
|
3391
|
+ foreach ($subordinatesOfCurrentLevel as $subordinate) {
|
|
|
3392
|
+ $subordinateId = $subordinate['uid'];
|
|
|
3393
|
+ $subordinateContribution = $subordinate['contribute'] ?? 0; // 安全获取,默认为0
|
|
|
3394
|
+
|
|
|
3395
|
+ // 累加下一层级的总贡献值
|
|
|
3396
|
+ // 注意:这里简单累加,如果一个下级同时被当前层多个用户推荐,其贡献会被计算多次
|
|
|
3397
|
+ // 如果要求每个下级只贡献一次(即使有多个上级),需要调整逻辑,
|
|
|
3398
|
+ // 例如在累加前检查 $processedSubordinateIds
|
|
|
3399
|
+
|
|
|
3400
|
+ // --- 修改点:确保每个下级贡献只被计算一次 ---
|
|
|
3401
|
+ // if (!isset($processedSubordinateIds[$subordinateId])) { // 如果这个下级还没被处理过
|
|
|
3402
|
+ $nextLevelTotalContribution += (float)$subordinateContribution;
|
|
|
3403
|
+ // }
|
|
|
3404
|
+ // 注释掉上面的检查,因为用户描述似乎是按层级直接累加,不管这个下级是否被上层处理过。
|
|
|
3405
|
+ // 如果A1和A2都属于第1层,他们各自的下级B1和B2都属于第2层,B1和B2的贡献值直接加到第2层的总和里。
|
|
|
3406
|
+ // 如果需要严格按“人”计算,即使一个人出现在多层或被多人推荐也只算一次,则需要解开注释并调整
|
|
|
3407
|
+
|
|
|
3408
|
+ // 收集下一轮需要查询的用户ID,同样需要防止重复处理
|
|
|
3409
|
+ if (!isset($processedSubordinateIds[$subordinateId])) {
|
|
|
3410
|
+ $nextLevelIds[] = $subordinateId;
|
|
|
3411
|
+ // 标记这个下级ID已处理过,避免在更深层级中再次将其加入查询队列
|
|
|
3412
|
+ $processedSubordinateIds[$subordinateId] = true;
|
|
|
3413
|
+ }
|
|
|
3414
|
+
|
|
|
3415
|
+ }
|
|
|
3416
|
+
|
|
|
3417
|
+ // 存储下一层级的总贡献值 (只有当贡献值大于0或你想记录空层级时)
|
|
|
3418
|
+ // 根据例子,我们只记录有贡献的层级,或者至少有用户的层级
|
|
|
3419
|
+ if (!empty($subordinatesOfCurrentLevel)) { // 只要找到了下级就记录该层
|
|
|
3420
|
+ $levelContributions[$nextLevel] = $nextLevelTotalContribution;
|
|
|
3421
|
+ }
|
|
|
3422
|
+
|
|
|
3423
|
+ // 准备下一轮迭代
|
|
|
3424
|
+ $currentLevelIds = array_unique($nextLevelIds); // 去重下一层的用户ID
|
|
|
3425
|
+ $currentLevel = $nextLevel; // 更新当前层级
|
|
|
3426
|
+ }
|
|
|
3427
|
+
|
|
|
3428
|
+ return $levelContributions;
|
|
|
3429
|
+ }
|
|
3228
|
3430
|
}
|