Переглянути джерело

Merge branch 'dev'

# Conflicts:
#	app/common/repositories/shared/SharedProsperityUserRepository.php
#	app/middleware/SecurityMiddleware.php
sunxbiao 5 місяців тому
батько
коміт
65014064f4

+ 33 - 0
app/common/dao/shared/SharedProsperityGroupDao.php

@@ -0,0 +1,33 @@
1
+<?php
2
+
3
+namespace app\common\dao\shared;
4
+
5
+use app\common\dao\BaseDao;
6
+use app\common\model\BaseModel;
7
+use app\common\model\shared\SharedProsperityGroup;
8
+
9
+class SharedProsperityGroupDao extends BaseDao
10
+{
11
+
12
+    /**
13
+     * @return BaseModel
14
+     */
15
+    protected function getModel(): string
16
+    {
17
+        return SharedProsperityGroup::class;
18
+    }
19
+
20
+    /**
21
+     * 获取所有团队配置
22
+     * @return array
23
+     */
24
+    public function getAllGroups(): array
25
+    {
26
+        try {
27
+            return $this->getModel()::select()->toArray();
28
+        } catch (\Exception $e) {
29
+            return [];
30
+        }
31
+    }
32
+
33
+}

+ 60 - 0
app/common/dao/shared/SharedProsperityGroupUserDao.php

@@ -0,0 +1,60 @@
1
+<?php
2
+
3
+namespace app\common\dao\shared;
4
+
5
+use app\common\dao\BaseDao;
6
+use app\common\model\BaseModel;
7
+use app\common\model\shared\SharedProsperityGroupUser;
8
+use think\db\exception\DbException;
9
+
10
+class SharedProsperityGroupUserDao extends BaseDao
11
+{
12
+
13
+    /**
14
+     * @return BaseModel
15
+     */
16
+    protected function getModel(): string
17
+    {
18
+        return SharedProsperityGroupUser::class;
19
+    }
20
+
21
+    /**
22
+     * 获取按团队分组的有效用户ID列表
23
+     * @return array [group_id => [user_id1, user_id2, ...]]
24
+     */
25
+    public function getValidUsersGroupByGroup(): array
26
+    {
27
+        try {
28
+            $rows = $this->getModel()::where('status', 1)
29
+                ->field('group_id, user_id')
30
+                ->select()
31
+                ->toArray();
32
+            $grouped = [];
33
+            foreach ($rows as $row) {
34
+                $grouped[$row['group_id']][] = $row['user_id'];
35
+            }
36
+            return $grouped;
37
+        } catch (\Exception $e) {
38
+            return [];
39
+        }
40
+    }
41
+
42
+    /**
43
+     * @param $groupId
44
+     * @return array
45
+     * @author 史晨
46
+     * @date 2026/2/27 11:31
47
+     * 获取团队用户(分页)
48
+     */
49
+    public function getUserByLevel($groupId)
50
+    {
51
+        try {
52
+            return $this->getModel()::where('status', 1)
53
+                ->where(['group_id' => $groupId])
54
+                ->paginate(20)
55
+                ->toArray();
56
+        } catch (DbException $e) {
57
+            return [];
58
+        }
59
+    }
60
+}

+ 44 - 0
app/common/dao/shared/SharedProsperityUserDao.php

@@ -7,6 +7,7 @@ use app\common\enum\CommonEnum;
7 7
 use app\common\model\BaseModel;
8 8
 use app\common\model\shared\SharedProsperityUser;
9 9
 use app\entity\data\shared\SharedProsperityUserEntity;
10
+use think\db\exception\DbException;
10 11
 
11 12
 class SharedProsperityUserDao extends BaseDao
12 13
 {
@@ -232,6 +233,17 @@ class SharedProsperityUserDao extends BaseDao
232 233
         }
233 234
     }
234 235
 
236
+    public function updateRewardByUserId($userId, $field, $value)
237
+    {
238
+        try {
239
+            /** @var SharedProsperityUser $model */
240
+            $model = $this->getModel();
241
+            return $model::getDB()->where('user_id', $userId)->inc($field,$value)->update();
242
+        } catch (\Exception $e) {
243
+            return 0;
244
+        }
245
+    }
246
+
235 247
     /**
236 248
      * 按合伙人等级分组获取用户
237 249
      * @return array [partner_level => [user_id1, user_id2, ...]]
@@ -259,4 +271,36 @@ class SharedProsperityUserDao extends BaseDao
259 271
             return [];
260 272
         }
261 273
     }
274
+
275
+    /**
276
+     * @return array|void
277
+     * @author 史晨
278
+     * @date 2026/2/27 09:32
279
+     * 后台用户列表
280
+     */
281
+    public function adminList($where,$page)
282
+    {
283
+        /** @var SharedProsperityUser $model */
284
+        $model = $this->getModel();
285
+        try {
286
+            $list = $model::getDB()
287
+                ->where($where)
288
+                ->with([
289
+                    'user' => function ($query) {
290
+                        $query->field('uid,avatar,nickname,account');
291
+                    },
292
+                    'parent' => function ($query) {
293
+                        $query->field('uid,avatar,nickname,account');
294
+                    },
295
+                    'group' => function ($query) {
296
+                        $query->field('group_id,user_id');
297
+                    }
298
+                ])
299
+                ->paginate(['page' => $page, 'list_rows' => 20])
300
+                ->toArray();
301
+            return $list;
302
+        } catch (DbException $e) {
303
+            return [];
304
+        }
305
+    }
262 306
 }

+ 18 - 0
app/common/dao/user/UserDao.php

@@ -272,6 +272,11 @@ class UserDao extends BaseDao
272 272
         return User::getDB()->where('account', $account)->where('is_del', 0)->find();
273 273
     }
274 274
 
275
+    public function nicknameByUser($nickname)
276
+    {
277
+        return User::getDB()->where('nickname', $nickname)->where('is_del', 0)->find();
278
+    }
279
+
275 280
     /**
276 281
      * @param $uid
277 282
      * @return array
@@ -478,4 +483,17 @@ class UserDao extends BaseDao
478 483
             return [];
479 484
         }
480 485
     }
486
+
487
+    /**
488
+     * @param $uid
489
+     * @param $number
490
+     * @return mixed
491
+     * @author 史晨
492
+     * @date 2026/2/27 15:15
493
+     * 更新用户佣金
494
+     */
495
+    public function updateBrokeragePriceByUid($uid,$number)
496
+    {
497
+        return $this->getModel()::getDB()->where('uid', '=', $uid)->inc('brokerage_price',$number)->update();
498
+    }
481 499
 }

+ 18 - 0
app/common/model/shared/SharedProsperityGroup.php

@@ -0,0 +1,18 @@
1
+<?php
2
+
3
+namespace app\common\model\shared;
4
+
5
+use app\common\model\BaseModel;
6
+
7
+class SharedProsperityGroup extends BaseModel
8
+{
9
+    public static function tablePk(): ?string
10
+    {
11
+        return 'id';
12
+    }
13
+
14
+    public static function tableName(): string
15
+    {
16
+        return 'shared_prosperity_group';
17
+    }
18
+}

+ 18 - 0
app/common/model/shared/SharedProsperityGroupUser.php

@@ -0,0 +1,18 @@
1
+<?php
2
+
3
+namespace app\common\model\shared;
4
+
5
+use app\common\model\BaseModel;
6
+
7
+class SharedProsperityGroupUser extends BaseModel
8
+{
9
+    public static function tablePk(): ?string
10
+    {
11
+        return 'id';
12
+    }
13
+
14
+    public static function tableName(): string
15
+    {
16
+        return 'shared_prosperity_group_user';
17
+    }
18
+}

+ 16 - 0
app/common/model/shared/SharedProsperityUser.php

@@ -3,6 +3,7 @@
3 3
 namespace app\common\model\shared;
4 4
 
5 5
 use app\common\model\BaseModel;
6
+use app\common\model\user\User;
6 7
 
7 8
 class SharedProsperityUser extends BaseModel
8 9
 {
@@ -15,4 +16,19 @@ class SharedProsperityUser extends BaseModel
15 16
     {
16 17
         return 'shared_prosperity_user';
17 18
     }
19
+
20
+    public function user()
21
+    {
22
+        return $this->hasOne(User::class, 'uid', 'user_id');
23
+    }
24
+
25
+    public function parent()
26
+    {
27
+        return $this->hasOne(User::class, 'uid', 'parent_id');
28
+    }
29
+
30
+    public function group()
31
+    {
32
+        return $this->hasOne(SharedProsperityGroupUser::class, 'user_id', 'user_id');
33
+    }
18 34
 }

+ 48 - 0
app/common/repositories/finance/FinanceRepository.php

@@ -11,6 +11,8 @@
11 11
 namespace app\common\repositories\finance;
12 12
 // use app\common\dao\article\ArticleDao;
13 13
 // use app\common\model\article\ArticleContent;
14
+use app\common\enum\CommonEnum;
15
+use app\common\enum\shared\SharedProsperityRewardRecordEnum;
14 16
 use app\common\repositories\BaseRepository;
15 17
 use app\common\repositories\user\UserRepository;
16 18
 use think\Exception;
@@ -247,6 +249,14 @@ class FinanceRepository extends BaseRepository
247 249
             $todayCount = Db::name('order_merchant')->where($dayWhere)->count();
248 250
             $list6[] = ['count' => $weekCount, 'name' => '周订单总数'];
249 251
             $list6[] = ['count' => $todayCount, 'name' => '日订单总数'];
252
+
253
+            // 共富订单统计
254
+            $shared_mer_id = CommonEnum::DESIGN_MERCHANT_ID['SharedProsperity']['code'];
255
+            $sharedMoney = Db::name('store_order')->where($where)->where('mer_id', $shared_mer_id)->count();
256
+            $weekCount = Db::name('store_order')->where($weekWhere)->where('mer_id', $shared_mer_id)->count();
257
+            $todayCount = Db::name('store_order')->where($dayWhere)->where('mer_id', $shared_mer_id)->count();
258
+            $list7[] = ['count' => $weekCount, 'name' => '周订单总数'];
259
+            $list7[] = ['count' => $todayCount, 'name' => '日订单总数'];
250 260
     
251 261
     
252 262
             $data[] = ['className' => 'el-icon-s-goods', 'count' => set_price_rtrim($chengjiaomoney), 'name' => '会员专区订单总数', 'mer_id' => $mer_idhy, 'list' => $list1];
@@ -255,6 +265,7 @@ class FinanceRepository extends BaseRepository
255 265
             $data[] = ['className' => 'el-icon-s-goods', 'count' => set_price_rtrim($tuikuanmoney), 'name' => '复购区订单总数', 'mer_id' => $mer_idfg, 'list' => $list4];
256 266
             $data[] = ['className' => 'el-icon-s-goods', 'count' => set_price_rtrim($tuikuancount), 'name' => '三方平台订单总数', 'list' => $list5];
257 267
             $data[] = ['className' => 'el-icon-s-goods', 'count' => set_price_rtrim($tuikuanren), 'name' => '线下订单总数', 'list' => $list6];
268
+            $data[] = ['className' => 'el-icon-s-goods', 'count' => set_price_rtrim($sharedMoney), 'name' => '共富订单总数', 'mer_id' => $shared_mer_id, 'list' => $list7];
258 269
             return $data;
259 270
         }
260 271
     }
@@ -375,6 +386,18 @@ class FinanceRepository extends BaseRepository
375 386
             $data['tow'][] = ['className' => 'el-icon-s-goods', 'count' => set_price_rtrim($maker[0]['count'] ?? 0), 'name' => '股权', 'user_group' => 0];
376 387
             $maker = Db::query("SELECT count(uid) as count FROM `rrx_merchant` where {$where}");
377 388
             $data['tow'][] = ['className' => 'el-icon-s-goods', 'count' => set_price_rtrim($maker[0]['count'] ?? 0), 'name' => '商户', 'user_group' => 0];
389
+
390
+            // 共富会员身份
391
+            $sharedUserDataQuery = Db::query("SELECT partner_level,count(user_id) count FROM `rrx_shared_prosperity_user` group by partner_level");
392
+            $sharedUserDataQuery = array_column($sharedUserDataQuery, 'count', 'partner_level');
393
+            $data['three'][] = ['className' => 'el-icon-s-goods', 'count' => (int)($sharedUserDataQuery[0] ?? 0), 'name' => '普通用户', 'partner_level' => 0];
394
+            $data['three'][] = ['className' => 'el-icon-s-goods', 'count' => (int)($sharedUserDataQuery[1] ?? 0), 'name' => '一星合伙人', 'partner_level' => 1];
395
+            $data['three'][] = ['className' => 'el-icon-s-goods', 'count' => (int)($sharedUserDataQuery[2] ?? 0), 'name' => '二星合伙人', 'partner_level' => 2];
396
+            $data['three'][] = ['className' => 'el-icon-s-goods', 'count' => (int)($sharedUserDataQuery[3] ?? 0), 'name' => '三星合伙人', 'partner_level' => 3];
397
+            $data['three'][] = ['className' => 'el-icon-s-goods', 'count' => (int)($sharedUserDataQuery[4] ?? 0), 'name' => '钻石合伙人', 'partner_level' => 4];
398
+            $data['three'][] = ['className' => 'el-icon-s-goods', 'count' => (int)($sharedUserDataQuery[5] ?? 0), 'name' => '总裁合伙人', 'partner_level' => 5];
399
+            $data['three'][] = ['className' => 'el-icon-s-goods', 'count' => (int)($sharedUserDataQuery[6] ?? 0), 'name' => '联席主席团', 'partner_level' => 6];
400
+
378 401
             $res['left'] = $data;
379 402
         }
380 403
         return $res;
@@ -448,6 +471,31 @@ class FinanceRepository extends BaseRepository
448 471
         $data[] = ['className' => 'el-icon-s-goods', 'count' => $weekCount, 'name' => '会员专区本周总业绩'];
449 472
         $data[] = ['className' => 'el-icon-s-goods', 'count' => $todayCount, 'name' => '会员专区今日总业绩'];
450 473
 
474
+
475
+        // 共富会员概况
476
+        $sWeekWhere = " 1=1";
477
+        $weekWhere = " 1=1";
478
+        $dayWhere = " 1=1";
479
+        //上周时间条件
480
+        $sWeekWhere .= " and DATE(create_time) >= '" . $startDate . "' and DATE(create_time) <= '" . $endDate . "'";
481
+        //周时间条件
482
+        $weekWhere .= " and DATE(create_time) >= '" . $oneWeekAgoFormatted . "' and DATE(create_time) <= '" . $todayFormatted . "'";
483
+        //今日时间条件
484
+        $dayWhere .= " and DATE(create_time) = '" . $todayFormatted . "'";
485
+        $sharedUserCount = Db::name('shared_prosperity_user')->count(); //共富会员总人数
486
+        $sharedUserDayCount = Db::name('shared_prosperity_user')->where($dayWhere)->count(); //共富今日新增会员
487
+        $sharedUserPvCount = Db::name('shared_prosperity_reward_record')->where(['type'=>SharedProsperityRewardRecordEnum::TYPE['PV']['code']])->sum('number'); // 共富会员专区总业绩
488
+        $sharedUserLastWeekPv = Db::name('shared_prosperity_reward_record')->where($sWeekWhere)->where(['type'=>SharedProsperityRewardRecordEnum::TYPE['PV']['code']])->sum('number'); // 共富会员专区上周总业绩
489
+        $sharedUserWeekPv = Db::name('shared_prosperity_reward_record')->where($weekWhere)->where(['type'=>SharedProsperityRewardRecordEnum::TYPE['PV']['code']])->sum('number'); // 共富会员专区本周总业绩
490
+        $sharedUserTodayPv = Db::name('shared_prosperity_reward_record')->where($dayWhere)->where(['type'=>SharedProsperityRewardRecordEnum::TYPE['PV']['code']])->sum('number'); // 共富会员专区今日总业绩
491
+
492
+        $data[] = ['className' => 'el-icon-s-goods', 'count' => $sharedUserCount, 'name' => '共富会员总人数'];
493
+        $data[] = ['className' => 'el-icon-s-goods', 'count' => $sharedUserDayCount, 'name' => '共富今日新增会员'];
494
+        $data[] = ['className' => 'el-icon-s-goods', 'count' => $sharedUserPvCount, 'name' => '共富会员专区总业绩'];
495
+        $data[] = ['className' => 'el-icon-s-goods', 'count' => $sharedUserLastWeekPv, 'name' => '共富会员专区上周总业绩'];
496
+        $data[] = ['className' => 'el-icon-s-goods', 'count' => $sharedUserWeekPv, 'name' => '共富会员专区本周总业绩'];
497
+        $data[] = ['className' => 'el-icon-s-goods', 'count' => $sharedUserTodayPv, 'name' => '共富会员专区今日总业绩'];
498
+
451 499
         $res['left'][] = $data;
452 500
         return $res;
453 501
     }

+ 298 - 13
app/common/repositories/shared/SharedProsperityTaskRepository.php

@@ -3,13 +3,18 @@
3 3
 namespace app\common\repositories\shared;
4 4
 
5 5
 use app\common\dao\shared\SharedProsperityBalanceLogDao;
6
+use app\common\dao\shared\SharedProsperityGroupDao;
7
+use app\common\dao\shared\SharedProsperityGroupUserDao;
6 8
 use app\common\dao\shared\SharedProsperityPointLogDao;
7 9
 use app\common\dao\shared\SharedProsperityRecommendConfigDao;
8 10
 use app\common\dao\shared\SharedProsperityUserDao;
9 11
 use app\common\enum\CommonEnum;
12
+use app\common\enum\dividend\DividendLogEnum;
13
+use app\common\enum\shared\SharedProsperityBalanceLogEnum;
10 14
 use app\common\enum\shared\SharedProsperityRewardRecordEnum;
11 15
 use app\common\repositories\BaseRepository;
12 16
 use app\common\repositories\user\UserBillRepository;
17
+use app\entity\data\dividend\DividendLogEntity;
13 18
 use think\facade\Db;
14 19
 use think\facade\Log;
15 20
 
@@ -19,9 +24,27 @@ class SharedProsperityTaskRepository extends BaseRepository
19 24
 
20 25
     const REWARD_TYPE_PV = SharedProsperityRewardRecordEnum::TYPE['PV']['code'];
21 26
 
27
+    // 临时分配规则
28
+    const CONFIG = [
29
+        // 用户
30
+        0 => "1.00",
31
+        // 一星合伙人
32
+        1 => "10.00",
33
+        // 二星合伙人
34
+        2 => "8.00",
35
+        // 三星合伙人
36
+        3 => "5.00",
37
+        // 钻石合伙人
38
+        4 => "3.00",
39
+        // 总裁合伙人
40
+        5 => "2.00",
41
+        // 联席主席团
42
+        6 => "1.00"
43
+    ];
44
+
22 45
     /**
23 46
      * @param $data
24
-     * @return void
47
+     * @return array 分配明细数据
25 48
      * @throws \Exception
26 49
      * @author 史晨
27 50
      * @date 2026/2/10 10:10
@@ -30,9 +53,9 @@ class SharedProsperityTaskRepository extends BaseRepository
30 53
     public function partner($data)
31 54
     {
32 55
         // 获取时间范围内订单
33
-        $merId = CommonEnum::DESIGN_MERCHANT_ID['SharedProsperity']['code'];
34 56
         $start = $data['startTime'];
35 57
         $end = $data['endTime'];
58
+        $isTest = $data['isTest'] ?? false; // 是否测试模式(不实际发放)
36 59
 
37 60
         // 获取pv
38 61
         /** @var SharedProsperityRewardRecordRepository $rewardRecordRepository */
@@ -46,10 +69,13 @@ class SharedProsperityTaskRepository extends BaseRepository
46 69
         $conPri = floor($totalConPri * self::PARTNER_RADIO * 100) / 100;
47 70
 
48 71
         // 获取合伙人分配规则
49
-        /** @var SharedProsperityRecommendConfigDao $configDao */
50
-        $configDao = app()->make(SharedProsperityRecommendConfigDao::class);
51
-        $config = $configDao->getConfigList(false);
52
-        $config = array_column($config, 'profit_ratio', 'level');
72
+        $config = self::CONFIG;
73
+        if (empty($config)) {
74
+            /** @var SharedProsperityRecommendConfigDao $configDao */
75
+            $configDao = app()->make(SharedProsperityRecommendConfigDao::class);
76
+            $config = $configDao->getConfigList(false);
77
+            $config = array_column($config, 'profit_ratio', 'level');
78
+        }
53 79
         if (empty($config)) {
54 80
             throw new \Exception('没有合伙人分配规则');
55 81
         }
@@ -61,7 +87,14 @@ class SharedProsperityTaskRepository extends BaseRepository
61 87
         /** @var SharedProsperityBalanceLogDao $balanceDao */
62 88
         $balanceDao = app()->make(SharedProsperityBalanceLogDao::class);
63 89
 
64
-        Db::startTrans();
90
+        // 分配明细数据收集
91
+        $distributionDetails = [];
92
+
93
+        // 如果是测试模式,不开启事务,只计算不实际发放
94
+        if (!$isTest) {
95
+            Db::startTrans();
96
+        }
97
+
65 98
         try {
66 99
             foreach ($users as $key => $userIds) {
67 100
                 if ($key == 0) {
@@ -69,7 +102,7 @@ class SharedProsperityTaskRepository extends BaseRepository
69 102
                 }
70 103
                 $radio = $config[$key];
71 104
                 // 该等级总分红
72
-                $levelTotal = floor(($conPri * ($radio / 100)) * 100) / 100;
105
+                $levelTotal = bcmul($conPri, bcdiv($radio, 100, 2), 2);
73 106
 
74 107
                 // 获取该等级所有用户的基本信息
75 108
                 $userInfos = $userDao->getSharedProsperityUserEntityListByUserIdList($userIds);
@@ -91,20 +124,58 @@ class SharedProsperityTaskRepository extends BaseRepository
91 124
                     $eachReward = floor(($levelTotal / $userNum) * 100) / 100;
92 125
                     foreach ($userInfos as $userInfo) {
93 126
                         $userReward = $eachReward;
94
-                        $this->distributeReward($userInfo, $userReward, $radio, $levelTotal, $balanceDao, $userDao);
127
+                        $weight = 1 / $userNum; // 平均分配的权重
128
+                        // 收集分配明细
129
+                        $distributionDetails[] = [
130
+                            'user_id' => $userInfo->getUserId(), //用户ID
131
+                            'level' => $key, //合伙人等级
132
+                            'total_allocation' => $levelTotal, //该等级总分配金额
133
+                            'team_pv' => $teamPvMap[$userInfo->getUserId()] ?? 0, //个人团队PV
134
+                            'current_level_team_pv' => $totalTeamPv, //当前等级所有用户的团队PV总和
135
+                            'ratio' => $weight, //占比(个人团队PV/当前等级团队PV)
136
+                            'actual_amount' => $userReward,//实际发放金额
137
+                        ];
138
+                        $this->distributeReward($userInfo, $userReward, $radio, $levelTotal, $balanceDao, $userDao, $isTest);
95 139
                     }
96 140
                 } else {
97 141
                     // 加权分配
98 142
                     foreach ($userInfos as $userInfo) {
99 143
                         $weight = $teamPvMap[$userInfo->getUserId()] / $totalTeamPv;
100 144
                         $userReward = floor($levelTotal * $weight * 100) / 100;
101
-                        $this->distributeReward($userInfo, $userReward, $radio, $levelTotal, $balanceDao, $userDao);
145
+                        // 收集分配明细
146
+                        $distributionDetails[] = [
147
+                            'user_id' => $userInfo->getUserId(),//用户ID
148
+                            'level' => $key,//合伙人等级
149
+                            'total_allocation' => $levelTotal,//该等级总分配金额
150
+                            'team_pv' => $teamPvMap[$userInfo->getUserId()] ?? 0,//个人团队PV
151
+                            'current_level_team_pv' => $totalTeamPv,//当前等级所有用户的团队PV总和
152
+                            'ratio' => $weight,//占比(个人团队PV/当前等级团队PV)
153
+                            'actual_amount' => $userReward,//实际发放金额
154
+                        ];
155
+                        $this->distributeReward($userInfo, $userReward, $radio, $levelTotal, $balanceDao, $userDao, $isTest);
102 156
                     }
103 157
                 }
104 158
             }
105
-            Db::commit();
159
+
160
+            if (!$isTest) {
161
+                // 记录分红日志
162
+                // $this->dividendLog($start, $end, $conPri, $conPri, $config, $isTest, '共富体系合伙人分红');
163
+                Db::commit();
164
+            }
165
+
166
+            // 返回分配明细数据
167
+            return [
168
+                'success' => true,
169
+                'is_test' => $isTest,
170
+                'total_pv' => $totalConPri,
171
+                'allocatable_profit' => $conPri,
172
+                'distribution_details' => $distributionDetails,
173
+                'config' => $config,
174
+            ];
106 175
         } catch (\Exception $e) {
107
-            Db::rollback();
176
+            if (!$isTest) {
177
+                Db::rollback();
178
+            }
108 179
             throw new \Exception($e->getMessage());
109 180
         }
110 181
     }
@@ -117,11 +188,19 @@ class SharedProsperityTaskRepository extends BaseRepository
117 188
      * @param $levelTotal
118 189
      * @param $balanceDao
119 190
      * @param $userDao
191
+     * @param bool $isTest 是否测试模式(不实际发放)
120 192
      * @return void
121 193
      */
122
-    private function distributeReward($userInfo, $userReward, $radio, $levelTotal, $balanceDao, $userDao)
194
+    private function distributeReward($userInfo, $userReward, $radio, $levelTotal, $balanceDao, $userDao, $isTest = false)
123 195
     {
124 196
         $userId = $userInfo->getUserId();
197
+
198
+        // 如果是测试模式,只记录日志不实际执行数据库操作
199
+        if ($isTest) {
200
+            Log::info("测试模式:用户 {$userId} 应发放奖励 {$userReward},等级 {$userInfo->getPartnerLevel()},比例 {$radio},等级总分红 {$levelTotal}");
201
+            return;
202
+        }
203
+
125 204
         $balanceDao->create([
126 205
             'user_id' => $userId,
127 206
             'level' => $userInfo->getPartnerLevel(),
@@ -163,6 +242,23 @@ class SharedProsperityTaskRepository extends BaseRepository
163 242
         $userDao->updateByUserId($userId, ['balance' => ['inc', $userReward]]);
164 243
     }
165 244
 
245
+    // private function dividendLog($startTime, $endTime, $performance, $allocated, $starList, $isTest, $remark)
246
+    // {
247
+    //     // 组装日志信息
248
+    //     /** @var DividendLogEntity $dividendLogEntity */
249
+    //     $dividendLogEntity = DividendLogEntity::newInstance();
250
+    //     $dividendLogEntity->setType(DividendLogEnum::TYPE['SharedProsperityPartnerProfit']['code'])
251
+    //         ->setStartTime($startTime)
252
+    //         ->setEndTime($endTime)
253
+    //         ->setPerformance($performance)
254
+    //         ->setAbatement(json_encode([]))
255
+    //         ->setAllocated($allocated)
256
+    //         ->setRule(json_encode($starList))
257
+    //         ->setIsTest($isTest)
258
+    //         ->setRemark($remark)
259
+    //         ->setExpected();
260
+    // }
261
+
166 262
     /**
167 263
      * @param $data
168 264
      * @return true
@@ -264,4 +360,193 @@ class SharedProsperityTaskRepository extends BaseRepository
264 360
             throw new \Exception($e->getMessage());
265 361
         }
266 362
     }
363
+
364
+    /**
365
+     * @param $data
366
+     * @return array 分配明细数据
367
+     * @throws \Exception
368
+     * @author 史晨
369
+     * @date 2026/2/14 10:54
370
+     * 共富奖(团队平均分配)
371
+     */
372
+    public function group($data)
373
+    {
374
+        // 获取时间范围内订单
375
+        $start = $data['startTime'];
376
+        $end = $data['endTime'];
377
+        $isTest = $data['isTest'] ?? false; // 是否测试模式(不实际发放)
378
+
379
+        // 获取pv
380
+        /** @var SharedProsperityRewardRecordRepository $rewardRecordRepository */
381
+        $rewardRecordRepository = app()->make(SharedProsperityRewardRecordRepository::class);
382
+        $orderList = $rewardRecordRepository->getListByTime($start, $end, self::REWARD_TYPE_PV);
383
+        if (empty($orderList)) {
384
+            throw new \Exception('没有订单');
385
+        }
386
+        // 计算总PV
387
+        $totalPv = array_sum(array_column($orderList, 'number'));
388
+        $totalPv = 100;
389
+        // 可分配总额 = 总PV * 15%
390
+        $totalAllocatable = floor($totalPv * 0.15 * 100) / 100;
391
+
392
+        // 获取团队配置
393
+        /** @var SharedProsperityGroupDao $groupDao */
394
+        $groupDao = app()->make(SharedProsperityGroupDao::class);
395
+        $groups = $groupDao->getAllGroups(); // 获取所有团队等级
396
+        if (empty($groups)) {
397
+            throw new \Exception('没有团队配置');
398
+        }
399
+
400
+        // 按 group_id 映射比例
401
+        $groupRatios = [];
402
+        foreach ($groups as $group) {
403
+            $groupRatios[$group['id']] = [
404
+                'name' => $group['name'],
405
+                'radio' => $group['radio'], // 百分比,例如 8.00
406
+                'max' => $group['max']
407
+            ];
408
+        }
409
+
410
+        // 获取团队成员
411
+        /** @var SharedProsperityGroupUserDao $groupUserDao */
412
+        $groupUserDao = app()->make(SharedProsperityGroupUserDao::class);
413
+        $groupUsers = $groupUserDao->getValidUsersGroupByGroup(); // 获取有效用户按团队分组
414
+        if (empty($groupUsers)) {
415
+            throw new \Exception('没有团队成员');
416
+        }
417
+
418
+        /** @var SharedProsperityBalanceLogDao $balanceDao */
419
+        $balanceDao = app()->make(SharedProsperityBalanceLogDao::class);
420
+        /** @var SharedProsperityUserDao $userDao */
421
+        $userDao = app()->make(SharedProsperityUserDao::class);
422
+
423
+        // 分配明细数据收集
424
+        $distributionDetails = [];
425
+
426
+        // 如果是测试模式,不开启事务,只计算不实际发放
427
+        if ($isTest === 'false') {
428
+            Db::startTrans();
429
+        }
430
+
431
+        try {
432
+            foreach ($groupRatios as $groupId => $groupInfo) {
433
+                $ratio = $groupInfo['radio']; // 百分比
434
+                // 该团队等级总分配金额 = 总PV * ratio / 100
435
+                $groupTotal = floor($totalPv * $ratio / 100 * 100) / 100;
436
+                // 获取该团队等级下的有效用户
437
+                $userIds = $groupUsers[$groupId] ?? [];
438
+                if (empty($userIds)) {
439
+                    // 没有成员,跳过分配
440
+                    continue;
441
+                }
442
+                $userCount = count($userIds);
443
+                // 平均分配
444
+                $eachReward = floor(($groupTotal / $userCount) * 100) / 100;
445
+                // 获取用户信息
446
+                $userInfos = $userDao->getSharedProsperityUserEntityListByUserIdList($userIds);
447
+
448
+                if (empty($userInfos)) {
449
+                    continue;
450
+                }
451
+                foreach ($userInfos as $userInfo) {
452
+                    $userReward = $eachReward;
453
+                    // 收集分配明细
454
+                    $distributionDetails[] = [
455
+                        'user_id' => $userInfo->getUserId(),
456
+                        'group_id' => $groupId,
457
+                        'group_name' => $groupInfo['name'],
458
+                        'total_allocation' => $groupTotal,
459
+                        'user_count' => $userCount,
460
+                        'ratio' => $ratio,
461
+                        'actual_amount' => $userReward,
462
+                    ];
463
+                    $this->distributeGroupReward($userInfo, $userReward, $ratio, $groupTotal, $balanceDao, $userDao, $groupId, $isTest);
464
+                }
465
+            }
466
+
467
+            if ($isTest === 'false') {
468
+                // 记录分红日志
469
+                // $this->dividendLog($start, $end, $totalPv, $totalAllocatable, $groupRatios, $isTest, '共富体系团队奖');
470
+                Db::commit();
471
+            }
472
+
473
+            // 返回分配明细数据
474
+            return [
475
+                'success' => true,
476
+                'is_test' => $isTest,
477
+                'total_pv' => $totalPv,
478
+                'allocatable_profit' => $totalAllocatable,
479
+                'distribution_details' => $distributionDetails,
480
+                'group_ratios' => $groupRatios,
481
+            ];
482
+        } catch (\Exception $e) {
483
+            if ($isTest === 'false') {
484
+                Db::rollback();
485
+            }
486
+            throw new \Exception($e->getMessage());
487
+        }
488
+    }
489
+
490
+    /**
491
+     * 分发团队奖励(记录日志和更新余额)
492
+     * @param $userInfo
493
+     * @param $userReward
494
+     * @param $radio
495
+     * @param $groupTotal
496
+     * @param $balanceDao
497
+     * @param $userDao
498
+     * @param $isTest
499
+     * @return void
500
+     */
501
+    private function distributeGroupReward($userInfo, $userReward, $radio, $groupTotal, $balanceDao, $userDao, $groupId, $isTest)
502
+    {
503
+        $userId = $userInfo->getUserId();
504
+
505
+        // 如果是测试模式,只记录日志不实际执行数据库操作
506
+        if ($isTest === 'true') {
507
+            Log::info("测试模式:用户 {$userId} 应发放团队奖励 {$userReward},比例 {$radio},团队总分红 {$groupTotal}");
508
+            return;
509
+        }
510
+
511
+        $balanceDao->create([
512
+            'user_id' => $userId,
513
+            'level' => $groupId, // 共富团队等级
514
+            'radio' => $radio,
515
+            'total_profit' => $groupTotal,
516
+            'old' => $userInfo->getBalance(),
517
+            'number' => $userReward,
518
+            'after' => $userInfo->getBalance() + $userReward,
519
+            'type' => SharedProsperityBalanceLogEnum::TYPE['GROUP']['code']
520
+        ]);
521
+
522
+        $bill = [
523
+            'uid' => $userId,
524
+            'link_id' => 0,
525
+            'pm' => 1,
526
+            'title' => '共富体系团队奖',
527
+            'category' => 'now_money',
528
+            'type' => 'commission',
529
+            'number' => $userReward,
530
+            'balance' => 0,
531
+            'mark' => '共富体系团队奖明细入账',
532
+            'create_time' => date('Y-m-d H:i:s'),
533
+            'status' => 1,
534
+            'commission_type' => CommonEnum::COMMISSION_TYPE['SHARED_PROSPERITY_GROUP_COMMISSION']['code'],
535
+            'order_sn' => 0,
536
+            'tripartite' => 0,
537
+            'type_shop' => 0,
538
+            'mer_id' => 0,
539
+            'source' => 0,
540
+            'order_type' => 1,
541
+            'is_red_brokerage' => 0,
542
+            'gzc' => 3,
543
+            'take_time' => time(),
544
+            'district_id' => '',
545
+            'street_id' => '',
546
+            'month' => '',
547
+        ];
548
+
549
+        Db::name('user_bill')->insert($bill);
550
+        $userDao->updateByUserId($userId, ['balance' => ['inc', $userReward]]);
551
+    }
267 552
 }

+ 150 - 0
app/common/repositories/shared/SharedProsperityUserRepository.php

@@ -644,4 +644,154 @@ class SharedProsperityUserRepository extends BaseRepository
644 644
         }
645 645
         return null;
646 646
     }
647
+
648
+    public function adminList($params)
649
+    {
650
+        $page = $params['page'] ?? 1;
651
+        $where = [];
652
+        /** @var UserDao $userDao */
653
+        $userDao = app()->make(UserDao::class);
654
+
655
+        // 手机号搜索
656
+        if (isset($params['account']) && $params['account']) {
657
+            $userData = $userDao->accountByUser($params['account']);
658
+            $uid = 0;
659
+            if ($userData) {
660
+                $uid = $userData->uid;
661
+            }
662
+
663
+            $where[] = ['user_id', '=', $uid];
664
+        }
665
+
666
+        // 昵称搜索
667
+        if (isset($params['nickname']) && $params['nickname']) {
668
+            $userData = $userDao->nicknameByUser($params['nickname']);
669
+            $uid = 0;
670
+            if ($userData) {
671
+                $uid = $userData->uid;
672
+            }
673
+            $where[] = ['user_id', '=', $uid];
674
+        }
675
+
676
+        // 合伙人等级搜索
677
+        if (isset($params['partner_level']) && $params['partner_level']) {
678
+            $where[] = ['partner_level', '=', $params['partner_level']];
679
+        }
680
+
681
+        // 共富团等级搜索
682
+        if (isset($params['user_group']) && $params['user_group']) {
683
+            /** @var SharedProsperityGroupUserDao $groupUserDao */
684
+            $groupUserDao = app()->make(SharedProsperityGroupUserDao::class);
685
+            $groupUserData = $groupUserDao->getUserByLevel($params['user_group']);
686
+            $uids = array_column($groupUserData['data'], 'user_id');
687
+            $where[] = ['user_id', 'in', $uids];
688
+            $page = 1;
689
+        }
690
+
691
+        $list = $this->dao->adminList($where, $page);
692
+        return $list;
693
+    }
694
+
695
+    /**
696
+     * @param $userId
697
+     * @param $level
698
+     * @return int
699
+     * @author 史晨
700
+     * @date 2026/2/27 14:23
701
+     * 更新用户等级
702
+     */
703
+    public function updateLevel($userId, $level)
704
+    {
705
+        return $this->dao->updateByUserId($userId, ['partner_level' => $level]);
706
+    }
707
+
708
+    /**
709
+     * @param $userId
710
+     * @param $type
711
+     * @param $number
712
+     * @return bool
713
+     * @author 史晨
714
+     * @date 2026/2/27 15:16
715
+     * 更新用户奖励
716
+     */
717
+    public function updateReward($userId, $type, $number)
718
+    {
719
+        $map = [
720
+            1001 => 'consumer_stocks',
721
+            1002 => 'withdrawal_limit',
722
+            1003 => 'pv'
723
+        ];
724
+
725
+        try {
726
+            Db::startTrans();
727
+
728
+            $pm = 1;
729
+            $remark = '后台操作增加' . $number;
730
+            if ($number < 0) {
731
+                $pm = 0;
732
+                $remark = '后台操作减少' . abs($number);
733
+            }
734
+
735
+            if (isset($map[$type])) {
736
+                // 更新数据
737
+                $this->dao->updateRewardByUserId($userId, $map[$type], $number);
738
+                // 记录日志
739
+                $insertData = [
740
+                    'user_id' => $userId,
741
+                    'type' => $type,
742
+                    'pm' => $pm,
743
+                    'number' => abs($number),
744
+                    'balance' => 0,
745
+                    'status' => SharedProsperityRewardRecordEnum::STATUS['VALID']['code'],
746
+                    'type_shop' => SharedProsperityRewardRecordEnum::TYPE_SHOP['Platform']['code'],
747
+                    'order_sn' => 0,
748
+                    'take_time' => date('Y-m-d H:i:s', time()),
749
+                    'remark' => $remark,
750
+                    'create_time' => date('Y-m-d H:i:s', time()),
751
+                    'update_time' => date('Y-m-d H:i:s', time()),
752
+                ];
753
+                /** @var SharedProsperityRewardRecordDao $rewardRecordDao */
754
+                $rewardRecordDao = app()->make(SharedProsperityRewardRecordDao::class);
755
+                $rewardRecordDao->insertAll([$insertData]);
756
+            } else {
757
+                // 更新数据
758
+                /** @var UserDao $userDao */
759
+                $userDao = app()->make(UserDao::class);
760
+                $userDao->updateBrokeragePriceByUid($userId, $number);;
761
+                // 记录日志
762
+                $bill = [
763
+                    'uid' => $userId,
764
+                    'link_id' => 0,
765
+                    'pm' => $pm,
766
+                    'title' => $remark,
767
+                    'category' => 'now_money',
768
+                    'type' => 'commission',
769
+                    'number' => abs($number),
770
+                    'balance' => 0,
771
+                    'mark' => $remark,
772
+                    'create_time' => date('Y-m-d H:i:s'),
773
+                    'status' => 1,
774
+                    'commission_type' => CommonEnum::COMMISSION_TYPE['SHARED_PROSPERITY_PARTNER_COMMISSION']['code'],
775
+                    'order_sn' => 0,
776
+                    'tripartite' => 0,
777
+                    'type_shop' => 0,
778
+                    'mer_id' => 0,
779
+                    'source' => 0,
780
+                    'order_type' => 1,
781
+                    'is_red_brokerage' => 0,
782
+                    'gzc' => 3,
783
+                    'take_time' => time(),
784
+                    'district_id' => '',
785
+                    'street_id' => '',
786
+                    'month' => '',
787
+                ];
788
+                Db::name('user_bill')->insert($bill);
789
+            }
790
+            Db::commit();
791
+            return true;
792
+        } catch (\Exception $e) {
793
+            Db::rollback();
794
+            return false;
795
+        }
796
+    }
647 797
 }

+ 58 - 0
app/controller/admin/system/sharedProsperity/SharedProsperityUser.php

@@ -0,0 +1,58 @@
1
+<?php
2
+
3
+namespace app\controller\admin\system\sharedProsperity;
4
+use app\common\repositories\shared\SharedProsperityUserRepository;
5
+
6
+class SharedProsperityUser
7
+{
8
+    /**
9
+     * @return mixed
10
+     * @author 史晨
11
+     * @date 2026/2/27 09:33
12
+     * 共富用户列表
13
+     */
14
+    public function list()
15
+    {
16
+        /** @var SharedProsperityUserRepository $repository */
17
+        $repository = app()->make(SharedProsperityUserRepository::class);
18
+        $params = app('request')->params(['account', 'nickname', 'partner_level', 'user_group', 'page']);
19
+        $list = $repository->adminList($params);
20
+        return app('json')->success($list);
21
+    }
22
+
23
+    /**
24
+     * @return mixed
25
+     * @author 史晨
26
+     * @date 2026/2/27 14:23
27
+     * 更新用户等级
28
+     */
29
+    public function updateLevel()
30
+    {
31
+        /** @var SharedProsperityUserRepository $repository */
32
+        $repository = app()->make(SharedProsperityUserRepository::class);
33
+        $params = app('request')->params(['user_id', 'partner_level']);
34
+        $res = $repository->updateLevel($params['user_id'], $params['partner_level']);
35
+        if (!$res) {
36
+            return app('json')->fail('更新失败');
37
+        }
38
+        return app('json')->success('更新成功');
39
+    }
40
+
41
+    /**
42
+     * @return mixed
43
+     * @author 史晨
44
+     * @date 2026/2/27 15:16
45
+     * 更新用户奖励
46
+     */
47
+    public function updateReward()
48
+    {
49
+        /** @var SharedProsperityUserRepository $repository */
50
+        $repository = app()->make(SharedProsperityUserRepository::class);
51
+        $params = app('request')->params(['user_id', 'type', 'number']);
52
+        $res = $repository->updateReward($params['user_id'], $params['type'], $params['number']);
53
+        if (!$res) {
54
+            return app('json')->fail('更新失败');
55
+        }
56
+        return app('json')->success('更新成功');
57
+    }
58
+}

+ 7 - 0
route/admin.php

@@ -118,6 +118,13 @@ Route::group(config('admin.api_admin_prefix') . '/', function () {
118 118
         Route::get('sharedProsperity/detail', 'admin.system.sharedProsperity.SharedProsperityRecommend/detail');
119 119
         Route::post('sharedProsperity/update', 'admin.system.sharedProsperity.SharedProsperityRecommend/update');
120 120
 
121
+        // 共富会员
122
+        Route::get('sharedProsperity/user/list', 'admin.system.sharedProsperity.SharedProsperityUser/list');
123
+        // 修改共富会员等级
124
+        Route::get('sharedProsperity/user/updateLevel', 'admin.system.sharedProsperity.SharedProsperityUser/updateLevel');
125
+        // 修改共富会员奖励
126
+        Route::get('sharedProsperity/user/updateReward', 'admin.system.sharedProsperity.SharedProsperityUser/updateReward');
127
+
121 128
         //组合数据
122 129
         Route::group('group', function () {
123 130
             Route::get('lst', '/lst')->name('groupLst');