浏览代码

Merge branch 'master' into liuzj-permission-dev

liuzejian 1 年之前
父节点
当前提交
ea8e6fa1b9
共有 59 个文件被更改,包括 2007 次插入403 次删除
  1. 4 1
      app/Exceptions/Handler.php
  2. 2 1
      composer.json
  3. 4 2
      modules/Channel/Http/Controllers/AdvertiserController.php
  4. 412 0
      modules/Channel/Http/Controllers/PayTemplateController.php
  5. 29 0
      modules/Channel/Http/Controllers/UserMiniprogramController.php
  6. 6 6
      modules/Channel/Installer.php
  7. 1 1
      modules/Channel/Models/BaseModel.php
  8. 1 2
      modules/Channel/Models/NoticeTypes.php
  9. 1 1
      modules/Channel/Models/Notices.php
  10. 14 0
      modules/Channel/Models/PayProduct.php
  11. 16 0
      modules/Channel/Models/PayTemplate.php
  12. 16 0
      modules/Channel/Models/PayTemplateItem.php
  13. 14 0
      modules/Channel/Models/UserHasMiniprograms.php
  14. 1 1
      modules/Channel/Models/UserNotice.php
  15. 14 0
      modules/Channel/Models/Users.php
  16. 0 2
      modules/Channel/Providers/ChannelServiceProvider.php
  17. 35 0
      modules/Channel/Services/User/UserService.php
  18. 20 2
      modules/Channel/routes/route.php
  19. 5 0
      modules/Common/Errors/Errors.php
  20. 37 0
      modules/Common/Models/BaseModel.php
  21. 148 0
      modules/CpManage/Http/Controllers/CpListController.php
  22. 234 0
      modules/CpManage/Http/Controllers/CpSubscribeStatisticDataController.php
  23. 63 0
      modules/CpManage/Http/Controllers/UserTrait.php
  24. 53 0
      modules/CpManage/Http/Requests/CpRequest.php
  25. 32 0
      modules/CpManage/Installer.php
  26. 34 0
      modules/CpManage/Middlewares/CpManageGate.php
  27. 13 0
      modules/CpManage/Models/Cp/CpCollection.php
  28. 11 0
      modules/CpManage/Models/Cp/CpSubscribeStatisticDataModel.php
  29. 81 0
      modules/CpManage/Models/Cp/Cps.php
  30. 32 0
      modules/CpManage/Providers/CpManageServiceProvider.php
  31. 49 0
      modules/CpManage/Services/CpManage/CpService.php
  32. 39 0
      modules/CpManage/routes/route.php
  33. 40 0
      modules/Manage/Enmus/MiniprogramType.php
  34. 102 0
      modules/Manage/Http/Controllers/MiniprogramController.php
  35. 115 0
      modules/Manage/Http/Controllers/UserMiniprogramController.php
  36. 53 0
      modules/Manage/Http/Requests/MiniprogramRequest.php
  37. 53 0
      modules/Manage/Http/Requests/MiniprogramUpdateRequest.php
  38. 32 0
      modules/Manage/Installer.php
  39. 30 0
      modules/Manage/Models/BaseModel.php
  40. 20 0
      modules/Manage/Models/Miniprogram.php
  41. 20 0
      modules/Manage/Providers/ManageServiceProvider.php
  42. 12 0
      modules/Manage/config/miniprogram.php
  43. 38 0
      modules/Manage/routes/route.php
  44. 3 1
      modules/User/Http/Controllers/AuthController.php
  45. 0 2
      modules/User/Http/Controllers/UserTrait.php
  46. 1 0
      modules/User/Models/User.php
  47. 1 1
      modules/Video/Http/Controllers/VideoController.php
  48. 0 9
      phpunit.xml
  49. 0 27
      tests/Common/Http/Controllers/OptionControllerTest.php
  50. 0 17
      tests/Common/Support/Trace/CustomizeLoggerTest.php
  51. 0 97
      tests/ContentManage/Http/Controllers/BookControllerTest.php
  52. 0 22
      tests/ContentManage/Http/Controllers/CpListControllerTest.php
  53. 0 62
      tests/ContentManage/Http/Controllers/CpSubscribeStatisticDataControllerTest.php
  54. 0 57
      tests/ContentManage/Output/OutputTest.php
  55. 0 18
      tests/ContentManage/Services/CP/SyncSubscribeTest.php
  56. 0 52
      tests/ContentManage/Services/CpManage/BookSettlementTest.php
  57. 1 1
      tests/Feature/ExampleTest.php
  58. 65 0
      tests/Feature/MiniprogramTest.php
  59. 0 18
      tests/Unit/ExampleTest.php

+ 4 - 1
app/Exceptions/Handler.php

@@ -65,7 +65,10 @@ class Handler extends ExceptionHandler
     public function render($request, Throwable $e): JsonResponse|Response
     {
         $message = $e->getMessage();
-
+        echo "<pre><hr>";
+        var_export($message);
+        echo  "<hr>";
+        die();
         if (method_exists($e, 'getStatusCode')) {
             if ($e->getStatusCode() == Response::HTTP_NOT_FOUND) {
                 $message = '路由未找到或未注册';

+ 2 - 1
composer.json

@@ -35,7 +35,8 @@
             "Database\\Seeders\\": "database/seeders/",
             "Modules\\": "modules",
             "\\": ""
-        },"files": [
+        },
+        "files": [
             "app/Libs/Helpers.php"
         ]
     },

+ 4 - 2
modules/Channel/Http/Controllers/AdvertiserController.php

@@ -80,9 +80,11 @@ class AdvertiserController extends CatchController
                 'users.deleted_at' => 0,
             ])->when($userContext['loginUserRoles']->contains('company'), function ($query) use($userContext){
                 return $query->where('users.pid' , $userContext['loginUser']->id);
-            })->when($userContext['loginUserRoles']->contains('optimizer'), function ($query) use ($userContext){
+            })
+            ->when($userContext['loginUserRoles']->contains('optimizer'), function ($query) use ($userContext){
                 return $query->where('users.id', $userContext['loginUser']->id);
-            })->when($email, function ($query, $email) {
+            })
+            ->when($email, function ($query, $email) {
                 return $query->where('users.email', $email);
             })->when($miniProgramId, function ($query, $miniProgramId){
                 return $query->where('user_has_miniprograms.miniprogram_id', $miniProgramId);

+ 412 - 0
modules/Channel/Http/Controllers/PayTemplateController.php

@@ -0,0 +1,412 @@
+<?php
+
+namespace Modules\Channel\Http\Controllers;
+
+use Carbon\Carbon;
+use Illuminate\Http\Request;
+use Catch\Base\CatchController;
+use Modules\Common\Errors\Errors;
+use Modules\Channel\Models\PayProduct;
+use Modules\Channel\Models\PayTemplate;
+use Modules\Channel\Models\PayTemplateItem;
+use Modules\Channel\Exceptions\ChannelBusinessException;
+use Modules\Channel\Services\User\UserService;
+
+class PayTemplateController extends CatchController
+{
+    public function __construct(protected readonly PayTemplate $payTemplate,protected readonly PayTemplateItem $payTemplateItem,protected readonly PayProduct $payProduct)
+    {
+        
+    }
+
+
+    private $sequence_map = [
+        '','位置一','位置二','位置三','位置四','位置五','位置六','位置七','位置八'
+    ];
+
+    /**
+     * 充值模板列表
+     *
+     * @param Request $request
+     * @return void
+     */
+    public function index(Request $request)
+    {
+        $uid = $this->getLoginUser()->id;
+        if(UserService::userHasRole($uid,'administrator')){
+            $uid = 0;
+        }
+        $name = $request->get('name');
+        $where = [[
+            'uid','=',$uid
+        ]];
+        if($name){
+            $where[] = ['name','like','%'.$name.'%']; 
+        }
+        return $this->payTemplate->where($where)->paginate(20);
+    }
+
+
+    /**
+     * 添加模板
+     *
+     * @param Request $request
+     * @return void
+     */
+    public function store(Request $request)
+    {
+        $uid = $this->getLoginUser()->id;
+        $name = $request->post('name');
+        $status = $request->post('status');
+        $options = $request->post('options');
+        if(empty($name) || empty($options)){
+            ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
+        }
+        if(UserService::userHasRole($uid,'administrator')){
+            $uid = 0;
+        }
+
+        $exists = $this->payTemplate->where('uid',$uid)->where('name',$name)->count();
+        if($exists){
+            ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_EXISTS_ERROR);
+        }
+        $option_list = json_decode($options,1);
+        $data = [];
+        $default_optioin = 0;
+        $option_cache = [];
+        $type_list = collect($this->optionTypeList())->pluck('value');
+        foreach($option_list as $option){
+            if(!is_numeric($option['price']) || !is_numeric($option['given'])){
+                ChannelBusinessException::throwError(Errors::PARAM_ERROR);
+            }
+            if($option['type'] == 'COIN' || $option['type'] == 'FIRST_COIN'){
+                if($option['given'] > 3*$option['price']*100){
+                    ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_GIVEN_TOO_MUCH);
+                    break;
+                }
+            }
+
+            if(!$type_list->contains($option['type'])){
+                ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_OPTIONS_ERROR);
+            }
+
+            if(in_array($option['price'],$option_cache)){
+                ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_CONFLICT);
+            }
+            $option_cache[] = $option['price'];
+
+            if(!$default_optioin && $option['is_default']){
+                $default_optioin = $option['price'];
+            }
+        }
+
+        $default_optioin = $default_optioin>0?$default_optioin:$option_list[0]['price'];
+
+        if($status == 1){
+            $this->payTemplate->where('uid',$uid)->update(['status'=>0]);
+        }
+
+        $pay_template_info = $this->payTemplate->create(['name'=>$name,'uid'=>$uid,'status'=>$status]);
+
+        foreach($option_list as $option){
+            $type = $option['type'];
+            if($option['type'] == 'COIN' || $option['type'] == 'FIRST_COIN'){
+                $type = 'COIN';
+            }
+            $product_info = $this->getPayProduct($option['price'], $type,$option['given']);
+            $data[] = [
+                'pay_template_id'=>$pay_template_info->id,'pay_product_id'=>$product_info->id,
+                'is_first_pay'=>$option['type'] == 'FIRST_COIN' ?1:0,'is_default'=>$option['price'] == $default_optioin ?1:0,
+                'status'=>1,'sequence'=>$option['sequence'],'created_at'=>Carbon::now(),'updated_at'=>Carbon::now()  
+            ];
+        }
+
+        $this->payTemplateItem->insert($data);
+        return [];
+    }
+
+    /**
+     * 模板详情
+     *
+     * @param int $id
+     * @return void
+     */
+    public function show($id)
+    {
+        //$uid = $this->getLoginUser()->id;
+        $uid= 1;
+        if(UserService::userHasRole($uid,'administrator')){
+            $uid = 0;
+        }
+        $exists = $this->payTemplate->where('uid',$uid)->where('id',$id)->first();
+        if(!$exists){
+            ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_NOT_EXISTS_ERROR);
+        }
+
+        $pay_template_item = $this->payTemplateItem->join('pay_products','pay_products.id','=','pay_template_items.pay_product_id')
+        ->where('pay_template_id',$id)
+        ->select('pay_products.price','pay_products.type','pay_products.given','pay_template_id','pay_product_id','is_first_pay','is_default','sequence','pay_template_items.id as pay_template_item_id')
+        ->where('pay_template_items.status',1)
+        ->orderBy('pay_template_items.sequence')
+        ->get();
+        $type_list = collect($this->optionTypeList());
+        foreach($pay_template_item as $item){
+            
+            if($item->type == 'COIN' && $item->is_first_pay == 1){
+                $item->type == 'FIRST_COIN';
+            }
+            $item->type_name = $type_list->where('value',$item->type)->first()['name'];
+            if($item->type == 'COIN' || $item->type == 'FIRST_COIN'){
+                $item->charge_coin = (int)($item->price*100);
+            }else{
+                $item->charge_coin = $item->type_name;
+            }
+
+            
+            $item->sequence_text = $this->sequence_map[$item->sequence];
+            $item->default_text = $item->is_default? '默认项':"非默认项";
+        }
+
+        return [
+            'template_info'=>$exists,
+            'template_item_list'=>$pay_template_item
+        ];
+    }
+
+    /**
+     * 更新模板
+     *
+     * @param [type] $id
+     * @param Request $request
+     * @return void
+     */
+    public function update($id, Request $request)
+    {
+        $name = $request->post('name');
+        $status = $request->post('status',-1);
+        $options = $request->post('options');
+        $uid = $this->getLoginUser()->id;
+        if(UserService::userHasRole($uid,'administrator')){
+            $uid = 0;
+        }
+        $exists = $this->payTemplate->where('uid',$uid)->where('id',$id)->first();
+        if(!$exists){
+            ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_NOT_EXISTS_ERROR);
+        }
+        $template_info_update = false;
+        if($name){
+            $template_info_update = true;
+            $exists->name = $name;
+        }
+        if($status != -1 && in_array($status,[1,0])){
+            $template_info_update = true;
+            $exists->status = $status;
+        }
+
+        if($status == 1){
+            $this->payTemplate->where('uid',$uid)->update(['status'=>0]);
+            $this->payTemplate->where('id',$id)->update(['status'=>1]);
+        }
+        if($template_info_update){
+            $exists->save();
+        }
+
+        if($options){
+            $option_list = json_decode($options,1);
+            $default_optioin = 0;
+            $option_cache = [];
+            $type_list = collect($this->optionTypeList())->pluck('value');
+            foreach($option_list as $option){
+                if($option['type'] == 'COIN' || $option['type'] == 'FIRST_COIN'){
+                    if($option['given'] > 3*$option['price']*100){
+                        ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_GIVEN_TOO_MUCH);
+                        break;
+                    }
+                }
+
+                if(!$type_list->contains($option['type'])){
+                    ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_OPTIONS_ERROR);
+                }
+
+                if(in_array($option['price'],$option_cache)){
+                    ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_CONFLICT);
+                }
+
+                $option_cache[] = $option['price'];
+
+                if(!$default_optioin && $option['is_default']){
+                    $default_optioin = $option['price'];
+                }
+
+            }
+            $this->payTemplateItem->where('pay_template_id',$id)->update(['status'=>0]);
+            $default_optioin = $default_optioin>0?$default_optioin:$option_list[0]['price'];
+            foreach($option_list as $option){
+                $type = $option['type'];
+                if($option['type'] == 'COIN' || $option['type'] == 'FIRST_COIN'){
+                    $type = 'COIN';
+                }
+                $product_info = $this->getPayProduct($option['price'], $type,$option['given']);
+            
+                $pay_template_item = $this->payTemplateItem->where('pay_template_id',$id)->where('pay_product_id',$product_info->id)->first();
+                if($pay_template_item){
+                    $pay_template_item->status = 1;
+                    $pay_template_item->sequence = $option['sequence'];
+                    $pay_template_item->is_first_pay = $option['type'] == 'FIRST_COIN' ?1:0;
+                    $pay_template_item->is_default = $option['price'] == $default_optioin ?1:0;
+                    $pay_template_item->save();
+                }else{
+                    $data = [
+                        'pay_template_id'=>$id,'pay_product_id'=>$product_info->id,
+                        'is_first_pay'=>$option['type'] == 'FIRST_COIN' ?1:0,'is_default'=>$option['price'] == $default_optioin ?1:0,
+                        'status'=>1,'sequence'=>$option['sequence'],'created_at'=>Carbon::now(),'updated_at'=>Carbon::now()  
+                    ];
+                    $this->payTemplateItem->insert($data);
+                }
+            }
+        }
+
+        return [];
+    }
+
+
+    /**
+     * 编辑单条选项
+     *
+     * @param [type] $id
+     * @param Request $request
+     * @return void
+     */
+    public function updatePayTemplateItem($id,Request $request){
+        $info = $this->payTemplateItem->find($id);
+        $price = $request->post('price');
+        $type = $request->post('type');
+        if(empty($price) || empty($type)){
+            ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
+        }
+        $given = $request->post('given',0);
+        if($given > 3*$price*100){
+            ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_GIVEN_TOO_MUCH);
+        }
+
+        $sequence = $request->post('sequence',0);
+        $is_default = $request->post('is_default',0);
+        $is_first_pay = 0;
+        if($type == 'FIRST_COIN'){
+            $type = 'COIN';
+            $is_first_pay = 1;
+        }
+        $product_info = $this->getPayProduct($price,$type,$given);
+        if($info->pay_product_id == $product_info->id){
+            $info->is_first_pay = $is_first_pay; 
+            $info->is_default = $is_default;
+            $info->save();
+        }else{
+            $info->status = 0;
+            $info->save();
+            $data = [
+                'pay_template_id'=>$info->pay_template_id,'pay_product_id'=>$product_info->id,
+                'is_first_pay'=>$is_first_pay,'is_default'=>$is_default,
+                'status'=>1,'sequence'=>$sequence,'created_at'=>Carbon::now(),'updated_at'=>Carbon::now()  
+            ];
+            $this->payTemplateItem->insert($data);
+        }
+
+        return [];
+    }
+
+
+
+    /**
+     * 删除单条选项
+     *
+     * @param [type] $id
+     * @return void
+     */
+    public function deleteOneItem($id){
+        $info = $this->payTemplateItem->find($id);
+        $info->status = 0;
+        $info->save();
+        return [];
+    }
+
+
+    /**
+     * 更新模板状态
+     *
+     * @param int $id
+     * @param Request $request
+     * @return void
+     */
+    public function updateStatus($id,Request $request){
+        $uid = $this->getLoginUser()->id;
+        if(UserService::userHasRole($uid,'administrator')){
+            $uid = 0;
+        }
+
+        $exists = $this->payTemplate->where('uid',$uid)->where('id',$id)->first();
+        $status = $request->post('status');
+        if(!in_array($status,[1,0])){
+            ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
+        }
+        if(!$exists){
+            ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_NOT_EXISTS_ERROR);
+        }
+        if($status == 1){
+            $this->payTemplate->where('uid',$uid)->update(['status'=>0]);
+        }
+
+        $exists->status = $status;
+        $exists->save();
+        return [];
+    }
+
+
+
+
+    private function getPayProduct($price,$type,$given){
+        $where = [
+            ['price','=',$price],
+            ['type','=',$type],
+            ['given','=',$given],
+        ];
+        $product_info = $this->payProduct->where($where)->first();
+        if($product_info){
+            return $product_info ;
+        }
+        return $this->payProduct->create(compact('price','type','given'));
+    }
+
+
+    public function optionTypeList(){
+        return [
+            ['name'=>'普通充值','value'=>'COIN'],
+            ['name'=>'首充','value'=>'FIRST_COIN'],
+            ['name'=>'包月','value'=>'MONTH'],
+            ['name'=>'包季','value'=>'QUARTER'],
+            ['name'=>'包年','value'=>'YEAR']
+        ];
+    }
+
+
+
+    public function optionTypeListOutPut(){
+        return collect($this->optionTypeList())->map(function($item){
+            return [
+                'type'=>$item['value'],'type_name'=>$item['name']
+            ];
+        })->all();
+    }
+
+
+    public function optionSequence(){
+        return [
+            ['sequence_text'=>'位置一','sequence'=>1],
+            ['sequence_text'=>'位置二','sequence'=>2],
+            ['sequence_text'=>'位置三','sequence'=>3],
+            ['sequence_text'=>'位置四','sequence'=>4],
+            ['sequence_text'=>'位置五','sequence'=>5],
+            ['sequence_text'=>'位置六','sequence'=>6]
+        ];
+    }
+}

+ 29 - 0
modules/Channel/Http/Controllers/UserMiniprogramController.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace Modules\Channel\Http\Controllers;
+
+use Catch\Base\CatchController;
+use Illuminate\Http\Request;
+use Modules\User\Models\User;
+use Modules\Channel\Models\UserHasMiniprograms;
+use Log;
+
+class UserMiniprogramController extends CatchController
+{
+    public function __construct(
+        protected readonly User $user,
+        protected readonly UserHasMiniprograms $userHasMiniprograms
+    ) {
+    }
+
+    public function index(Request $request)
+    {
+        $uid = $this->getLoginUser()->id;
+        Log::info('channel',['c'=>'UserMiniprogramController','uid'=>$uid]);
+        return $this->userHasMiniprograms->join('miniprogram','miniprogram.id','=','user_has_miniprograms.miniprogram_id')
+        ->where('user_has_miniprograms.is_enabled',1)
+        ->where('uid',$uid)
+        ->select('user_has_miniprograms.miniprogram_id','miniprogram.name','miniprogram.play_name')
+        ->get();
+    }
+}

+ 6 - 6
modules/Channel/Installer.php

@@ -1,9 +1,9 @@
 <?php
 
-namespace Modules\ContentManage;
+namespace Modules\Channel;
 
 use Catch\Support\Module\Installer as ModuleInstaller;
-use Modules\ContentManage\Providers\ContentManageServiceProvider;
+use Modules\Channel\Providers\ChannelServiceProvider;
 
 class Installer extends ModuleInstaller
 {
@@ -11,12 +11,12 @@ class Installer extends ModuleInstaller
     {
         // TODO: Implement info() method.
         return [
-            'title' => '内容中台',
-            'name' => 'contentManage',
-            'path' => 'contentManage',
+            'title' => '渠道管理',
+            'name' => 'channel',
+            'path' => 'channel',
             'keywords' => '内容中台',
             'description' => '内容中台管理模块',
-            'provider' => ContentManageServiceProvider::class
+            'provider' => ChannelServiceProvider::class
         ];
     }
 

+ 1 - 1
modules/Channel/Models/BaseModel.php

@@ -1,6 +1,6 @@
 <?php
 
-namespace Modules\System\Models;
+namespace Modules\Channel\Models;
 
 use Catch\Base\CatchModel as Model;
 use Illuminate\Database\Eloquent\Builder;

+ 1 - 2
modules/Channel/Models/NoticeTypes.php

@@ -1,7 +1,6 @@
 <?php
 
-namespace Modules\System\Models;
-
+namespace Modules\Channel\Models;
 
 
 class NoticeTypes extends BaseModel

+ 1 - 1
modules/Channel/Models/Notices.php

@@ -1,6 +1,6 @@
 <?php
 
-namespace Modules\System\Models;
+namespace Modules\Channel\Models;
 
 
 class Notices extends BaseModel

+ 14 - 0
modules/Channel/Models/PayProduct.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace Modules\Channel\Models;
+
+
+class PayProduct extends BaseModel
+{
+    protected $table = 'pay_products';
+
+    protected $fillable = [
+        'id', 'price', 'type', 'given', 'created_at', 'updated_at', 
+    ];
+
+}

+ 16 - 0
modules/Channel/Models/PayTemplate.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace Modules\Channel\Models;
+
+use Catch\Base\CatchModel as Model;
+
+
+class PayTemplate extends BaseModel
+{
+    protected $table = 'pay_templates';
+
+    protected $fillable = [
+        'id', 'name', 'uid','status', 'created_at', 'updated_at', 
+    ];
+
+}

+ 16 - 0
modules/Channel/Models/PayTemplateItem.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace Modules\Channel\Models;
+
+use Catch\Base\CatchModel as Model;
+
+
+class PayTemplateItem extends BaseModel
+{
+    protected $table = 'pay_template_items';
+
+    protected $fillable = [
+        'id', 'pay_template_id', 'pay_product_id', 'is_first_pay', 'is_default', 'status', 'sequence', 'created_at', 'updated_at', 
+    ];
+
+}

+ 14 - 0
modules/Channel/Models/UserHasMiniprograms.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace Modules\Channel\Models;
+
+
+class UserHasMiniprograms extends BaseModel
+{
+    protected $table = 'user_has_miniprograms';
+
+    protected $fillable = [
+        'id', 'uid', 'miniprogram_id', 'is_enabled', 'created_at', 'updated_at'
+    ];
+
+}

+ 1 - 1
modules/Channel/Models/UserNotice.php

@@ -1,6 +1,6 @@
 <?php
 
-namespace Modules\System\Models;
+namespace Modules\Channel\Models;
 
 
 class UserNotice extends BaseModel

+ 14 - 0
modules/Channel/Models/Users.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace Modules\Channel\Models;
+
+
+class Users extends BaseModel
+{
+    protected $table = 'users';
+
+    protected $fillable = [
+        'id', 'username', 'password', 'email', 'avatar', 'remember_token', 'department_id', 'creator_id', 'status', 'login_ip', 'login_at', 'created_at', 'updated_at', 'deleted_at', 'pid', 'remark', 
+    ];
+
+}

+ 0 - 2
modules/Channel/Providers/ChannelServiceProvider.php

@@ -2,9 +2,7 @@
 
 namespace Modules\Channel\Providers;
 
-use Catch\CatchAdmin;
 use Catch\Providers\CatchModuleServiceProvider;
-use Modules\ContentManage\Middlewares\ContentManageGate;
 
 class ChannelServiceProvider extends CatchModuleServiceProvider
 {

+ 35 - 0
modules/Channel/Services/User/UserService.php

@@ -0,0 +1,35 @@
+<?php
+/**
+ * ${CARET}
+ * @file:NoitceService.php
+ * @Created by gnitif
+ * @Date: 2023/3/27
+ * @Time: 11:54
+ */
+
+
+namespace Modules\Channel\Services\User;
+
+use Modules\Channel\Models\Users;
+
+class UserService {
+
+
+    public static function listByRole(string $identify, array $field){
+        return Users::join('user_has_roles','user_has_roles.user_id','=','users.id')
+        ->join('roles','roles.id','=','user_has_roles.role_id')
+        ->where('roles.identify',$identify)
+        ->select($field)
+        ->get();
+    }
+
+
+    public static function userHasRole(int $uid,string $identify){
+        return Users::join('user_has_roles','user_has_roles.user_id','=','users.id')
+        ->join('roles','roles.id','=','user_has_roles.role_id')
+        ->where('users.id',$uid)
+        ->where('roles.identify',$identify)
+        ->count();
+    }
+
+}

+ 20 - 2
modules/Channel/routes/route.php

@@ -2,8 +2,8 @@
 
 use Illuminate\Support\Facades\Route;
 use Modules\Channel\Http\Controllers\AdvertiserController;
-use Modules\System\Http\Controllers\NoticesController;
-use Modules\System\Http\Controllers\NoticeTypesController;
+use Modules\Channel\Http\Controllers\PayTemplateController;
+use Modules\Channel\Http\Controllers\UserMiniprogramController;
 
 Route::prefix('channel')->group(function () {
     Route::post('advertiser/add', [AdvertiserController::class, 'addAdvertiser']);
@@ -11,5 +11,23 @@ Route::prefix('channel')->group(function () {
 
     Route::get('advertiser/listAdvertiser', [AdvertiserController::class, 'listAdvertiser']);
     Route::get('advertiser/getAdvertiser', [AdvertiserController::class, 'getAdvertiser']);
+
+    Route::get('miniprogram/list', [UserMiniprogramController::class, 'index']);
+
+
+    //支付模板
+    Route::prefix('paytemplate')->group(function(){
+        Route::get('optionTypeList',[PayTemplateController::class,'optionTypeListOutPut'])->withoutMiddleware(config('catch.route.middlewares'));
+        Route::get('optionSequence',[PayTemplateController::class,'optionSequence'])->withoutMiddleware(config('catch.route.middlewares'));
+        Route::get('list',[PayTemplateController::class,'index']);
+        Route::get('show/{id}',[PayTemplateController::class,'show']);
+        Route::post('store',[PayTemplateController::class,'store']);
+        Route::post('update/{id}',[PayTemplateController::class,'update']);
+        Route::post('updateStatus/{id}',[PayTemplateController::class,'updateStatus']);//->withoutMiddleware(config('catch.route.middlewares'));;
+        Route::post('updatePayTemplateItem/{id}',[PayTemplateController::class,'updatePayTemplateItem']);
+        Route::get('deleteOneItem/{id}',[PayTemplateController::class,'deleteOneItem']);
+    });
+
+
 });
 

+ 5 - 0
modules/Common/Errors/Errors.php

@@ -11,6 +11,11 @@ class Errors
     public const  NO_OPERATE_PERMISSION= [500007, '用户无操作权限'];
     public const  VIDEO_NOT_EXISTS= [500008, '视频不存在'];
     public const  MINIPROGRAM_STATUS_ERROR= [500005, '小程序未启用'];
+    public const  PAY_TEMPLATE_EXISTS_ERROR= [500006, '充值模板已经存在'];
+    public const  PAY_TEMPLATE_GIVEN_TOO_MUCH= [500007, '赠送不能超过金额3倍'];
+    public const  PAY_TEMPLATE_NOT_EXISTS_ERROR= [500008, '充值模板不存在'];
+    public const  PAY_TEMPLATE_CONFLICT= [500008, '该档位已存在'];
+    public const  PAY_TEMPLATE_OPTIONS_ERROR= [500009, '类型不存在'];
     public const  UPLOAD_IMAGE_ERROR= [500006, '上传图片不成功'];
     public const  JULIANG_ACCOUNT_EXISTS= [500101, '巨量广告账户已经存在'];
     public const  CALLBACK_RATE_TIME_RANGE_ERROR= [500102, '回传比例时间区间不合法'];

+ 37 - 0
modules/Common/Models/BaseModel.php

@@ -0,0 +1,37 @@
+<?php
+/**
+ *  模型公共部分
+ * @file:${FILE_NAME}
+ * @Created by gnitif
+ * @Date: 2023/5/6
+ * @Time: 15:21
+ */
+
+
+namespace Modules\Common\Models;
+
+use Catch\Base\CatchModel as Model;
+use Illuminate\Database\Eloquent\Builder;
+
+class BaseModel extends Model
+{
+
+    protected array $defaultHidden = [];
+
+    protected array $defaultCasts = [
+        'created_at' => 'datetime:Y-m-d H:i:s',
+
+        'updated_at' => 'datetime:Y-m-d H:i:s',
+    ];
+    protected $dateFormat = '';
+
+    public static function bootSoftDeletes(): void{
+
+    }
+
+
+    public function scopeActive(Builder $query): void
+    {
+        $query->where($this->table.'.is_enabled', 1);
+    }
+}

+ 148 - 0
modules/CpManage/Http/Controllers/CpListController.php

@@ -0,0 +1,148 @@
+<?php
+/**
+ * ${CARET}
+ * @file:CpListController.php
+ * @Created by gnitif
+ * @Date: 2023/3/20
+ * @Time: 16:25
+ */
+
+
+namespace Modules\CpManage\Http\Controllers;
+
+use Catch\Base\CatchController as Controller;
+use Catch\Exceptions\FailedException;
+use Illuminate\Http\Request;
+use Modules\CpManage\Http\Requests\CpRequest;
+use Modules\CpManage\Models\Cp\CpCollection;
+use Modules\CpManage\Models\Cp\Cps;
+use Modules\CpManage\Services\CpManage\CpService;
+
+class CpListController extends Controller
+{
+    /**
+     * @param Cps $model
+     */
+    public function __construct(protected readonly Cps $model,protected readonly CpCollection $cpCollectionModel)
+    {
+
+    }
+
+    /**
+     * cp列表
+     * name: index
+     * @param CpRequest $request
+     * @return mixed
+     * date 2023/03/20 16:26
+     */
+    public function index(Request $request)
+    {
+        $where =[ ['is_deleted','=',0]];
+        if (!empty($request->get("cp_name", ''))){
+            $where[] = ['cp_name','like',"%".$request->get("cp_name", ''). "%"];
+        }
+        if (!empty($request->get("cp_company", ''))) {
+            $where[] = ['cp_company','like',"%".$request->get("cp_company", ''). "%"];
+        }
+
+        return  CpService::getCpList($where,$request->get('limit',15));
+    }
+
+    /**
+     *  添加
+     * name: store
+     * @param CpRequest $request
+     * @return mixed
+     * date 2023/03/23 13:50
+     */
+    public function store(CpRequest $request)
+    {
+        $params = $request->all();
+        return $this->model->storeBy($params);
+    }
+
+    /**
+     *  获取cp信息
+     * name: show
+     * @param $id
+     * @return mixed
+     * date 2023/03/23 13:50
+     */
+    public function show($id)
+    {
+
+        $cp =  $this->model->where('cp_id', $id)->first();
+        // [$cp['share_per_before'],$cp['share_per_after']] = explode(':',$cp['share_per']);
+        return $cp;
+    }
+
+    /**
+     *  编辑
+     * name: update
+     * @param $id
+     * @param CpRequest $request
+     * @return mixed
+     * date 2023/03/23 13:51
+     */
+    public function update($id, CpRequest $request)
+    {
+        $params = $request->all();
+        // $params['share_per'] = $params['share_per_before'] .":" .$params['share_per_after'];
+        if(isset($params['cp_name'])){
+            unset($params['cp_name']);
+        }
+        return $this->model->updateBy($id, $params);
+    }
+
+    /**
+     *  删除
+     * name: destroy
+     * @param $id
+     * date 2023/03/23 13:51
+     */
+    public function destroy($id)
+    {
+        return $this->model->deleteBy($id);
+    }
+
+    /**
+     * 获取cp现在选
+     * name: selectOptions
+     * @param Request $request
+     * @return mixed
+     * date 2023/03/23 13:51
+     */
+    public function selectOptions(Request $request)
+    {
+        $cpName = $request->input('cp_name','');
+        return CpService::selectOptions($cpName);
+
+    }
+
+
+    /**
+     * 采集
+     * @param Request $request
+     * @return void
+     */
+    public function cpCollection(Request $request){
+        $cpName = $request->get('cp_name');
+        $cpId = $request->get('cp_id');
+
+        if(empty($cpName) || empty($cpId) ){
+            throw new FailedException('缺少参数');
+        }
+
+
+        $status = $this->cpCollectionModel->where('cp_id',$cpId)->whereIn('spider_status',[0,1])->count();
+        if($status >0){
+            throw new FailedException('正在采集中');
+        }
+
+        $this->cpCollectionModel->create(['cp_id'=>$cpId,'cp_name'=>$cpName,'spider_status'=>0,'spider_result'=>'']);
+
+        return [];
+
+    }
+
+}

+ 234 - 0
modules/CpManage/Http/Controllers/CpSubscribeStatisticDataController.php

@@ -0,0 +1,234 @@
+<?php
+
+namespace Modules\CpManage\Http\Controllers;
+
+use Catch\Base\CatchController;
+use Illuminate\Foundation\Validation\ValidatesRequests;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+
+
+class CpSubscribeStatisticDataController extends CatchController
+{
+    use ValidatesRequests, UserTrait;
+
+
+    /**
+     * cp结算数据中心列表
+     * @param Request $request
+     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
+     * @throws \Illuminate\Validation\ValidationException
+     */
+    public function list(Request $request) {
+        $this->validate($request, [
+            'book_name' => 'nullable|string|max:256',
+            'bid' => 'nullable|integer|min:1',
+            'cp_name' => 'nullable|string|min:1',
+            'start_date' => 'nullable|date_format:Y-m-d',
+            'end_date' => 'nullable|date_format:Y-m-d',
+            'page' => 'required|integer|min:1',
+            'limit' => 'integer|min:10|max:300',
+            'is_export' => 'nullable|integer|in:0,1',   // 是否导出全部, 1-是,0-否
+            'final_amount_gt0' => 'nullable|integer|in:0,1', // 应结算金额是否要大于0,
+            'book_settlement_type' => 'nullable|in:share,bottomline', // 书籍合作模式
+        ]);
+        $bookName = $request->input('book_name');
+        $bid = $request->input('bid');
+        $cpName = $request->input('cp_name');
+        $startDate = $request->input('start_date');
+        $endDate = $request->input('end_date');
+        $perPage = $request->input('limit', 15);
+        $isExport = $request->input('is_export', 0);
+        $finalAmountGt0 = $request->input('final_amount_gt0', 0);
+        $bookSettlementType = $request->input('book_settlement_type');
+        $settlementTypes = [
+            'buyout' => '买断', 'bottomline' => '保底', 'share' => '分成', 'zhuishuyun' => '追书云计算'
+        ];
+
+        $cpName = $this->getUserCpName() ?? $cpName;
+
+
+        $sql = DB::table('cp_subscribe_statistic_data as statistic')
+            ->leftJoin('books as book', 'statistic.bid' , 'book.id')
+            ->when($bookName, function ($query, $bookName) {
+                return $query->where('book.name', 'like', '%'.$bookName. '%');
+            })->when($bid , function ($query, $bid) {
+                return $query->where(['statistic.bid' => $bid]);
+            })->when($cpName, function ($query, $cpName) {
+                return $query->where(['statistic.cp_name' => $cpName]);
+            })->when($startDate, function ($query, $startDate) {
+                $realStartDate = date_add(date_create($startDate), date_interval_create_from_date_string('1 day'))
+                    ->format('Y-m-d');
+                return $query->where('statistic.calculate_date', '>=', $realStartDate);
+            })->when($endDate, function ($query, $endDate) {
+                $realEndDate = date_add(date_create($endDate), date_interval_create_from_date_string('1 day'))
+                    ->format('Y-m-d');
+                return $query->where('statistic.calculate_date', '<=', $realEndDate);
+            })->when($finalAmountGt0, function ($query) {
+                return $query->where('statistic.yesterday_final_amount', '>', 0);
+            })->when($bookSettlementType, function ($query, $bookSettlementType){
+                return $query->where('statistic.book_settlement_type', $bookSettlementType);
+            })
+            ->select('statistic.bid', 'book.name as book_name', 'statistic.cp_name',
+            'statistic.yesterday_total_coins', 'statistic.yesterday_available_amount', 'statistic.yesterday_final_amount',
+            'statistic.calculate_date', 'statistic.book_settlement_type')
+            ->orderBy('statistic.calculate_date', 'desc')
+            ->orderBy('statistic.bid', 'desc');
+
+
+        if($isExport) {
+            return $sql->get()->map(function ($item) use($settlementTypes) {
+                $item->date = date_sub(date_create($item->calculate_date), date_interval_create_from_date_string('1 day'))
+                    ->format('Y-m-d');
+                $item->book_settlement_type_str = $settlementTypes[$item->book_settlement_type] ?? '';
+                return $item;
+            });
+        } else {
+            return $sql->paginate($perPage)->through(function ($item) use ($settlementTypes) {
+                $item->date = date_sub(date_create($item->calculate_date), date_interval_create_from_date_string('1 day'))
+                    ->format('Y-m-d');
+                $item->book_settlement_type_str = $settlementTypes[$item->book_settlement_type] ?? '';
+                return $item;
+            });
+        }
+
+
+
+    }
+
+    public function listStatistic(Request $request) {
+        $this->validate($request, [
+            'book_name' => 'nullable|string|max:256',
+            'bid' => 'nullable|integer|min:1',
+            'cp_name' => 'nullable|string|min:1',
+            'start_date' => 'nullable|date_format:Y-m-d',
+            'end_date' => 'nullable|date_format:Y-m-d',
+            'book_settlement_type' => 'nullable|in:share,bottomline'
+        ]);
+        $bookName = $request->input('book_name');
+        $bid = $request->input('bid');
+        $cpName = $request->input('cp_name');
+        $startDate = $request->input('start_date');
+        $endDate = $request->input('end_date');
+        $bookSettlementType = $request->input('book_settlement_type');
+
+        $cpName = $this->getUserCpName() ?? $cpName;
+
+        $res = DB::table('cp_subscribe_statistic_data as statistic')
+            ->leftJoin('books as book', 'statistic.bid' , 'book.id')
+            ->when($bookName, function ($query, $bookName) {
+                return $query->where('book.name', 'like', '%'.$bookName. '%');
+            })->when($bid , function ($query, $bid) {
+                return $query->where(['statistic.bid' => $bid]);
+            })->when($cpName, function ($query, $cpName) {
+                return $query->where(['statistic.cp_name' => $cpName]);
+            })->when($startDate, function ($query, $startDate) {
+                $realStartDate = date_add(date_create($startDate), date_interval_create_from_date_string('1 day'))
+                    ->format('Y-m-d');
+                return $query->where('statistic.calculate_date', '>=', $realStartDate);
+            })->when($endDate, function ($query, $endDate) {
+                $realEndDate = date_add(date_create($endDate), date_interval_create_from_date_string('1 day'))
+                    ->format('Y-m-d');
+                return $query->where('statistic.calculate_date', '<=', $realEndDate);
+            })->when($bookSettlementType, function ($query, $bookSettlementType){
+                return $query->where('statistic.book_settlement_type', $bookSettlementType);
+            })
+            ->select(
+                DB::raw('sum(yesterday_total_coins) as yesterday_total_coins'),
+                DB::raw('sum(yesterday_available_amount) as yesterday_available_amount'),
+                DB::raw('sum(yesterday_final_amount) as yesterday_final_amount')
+            )->first();
+
+        return $res;
+    }
+
+    /**
+     * cp结算列表
+     * @param Request $request
+     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
+     * @throws \Illuminate\Validation\ValidationException
+     */
+    public function monthList(Request $request) {
+        $this->validate($request, [
+            'cp_name' => 'nullable|string',
+            'start_month' => 'nullable|date_format:Y-m',
+            'end_month' => 'nullable|date_format:Y-m',
+            'page' => 'required|integer|min:1',
+            'limit' => 'integer|min:10',
+            'is_export' => 'integer|in:0,1'
+        ]);
+
+        $cpName = $request->input('cp_name');
+        $startMonth = $request->input('start_month');
+        $endMonth = $request->input('end_month');
+        $isExport = $request->input('is_export', 0);
+        $finalStateMap = ['notCheck' => '未结算', 'done' => '已结算'];
+
+        $cpName = $this->getUserCpName() ?? $cpName;
+        $sql =  DB::table('cp_subscribe_month_statistic_data as data')
+            ->leftJoin('cps as cp' , 'cp.cp_name', 'data.cp_name')
+            ->when($cpName, function ($query, $cpName){
+                return $query->where(['data.cp_name' => $cpName]);
+            })->when($startMonth, function ($query, $startMonth){
+                return $query->where('data.month', '>=', $startMonth);
+            })->when($endMonth, function ($query, $endMonth){
+                return $query->where('data.month', '<=', $endMonth);
+            })
+            ->select('data.id','data.month', 'cp.cp_id', 'cp.cp_name', 'cp.cp_company',
+            'data.book_num', 'data.final_amount', 'data.final_state', 'data.final_time')
+            ->orderBy('data.month', 'desc')
+            ->orderBy('cp.cp_id', 'desc');
+
+
+        if($isExport) {
+            return $sql->get()->map(function ($item) use ($finalStateMap){
+                $item->final_state_str = $finalStateMap[$item->final_state] ?? '';
+                return $item;
+            });
+        }else {
+            return $sql->paginate($request->integer('limit', 10));
+        }
+    }
+
+    public function saveFinalState(Request $request){
+        $this->validate($request, [
+            'id' => 'required|integer|min:1',
+            'final_state' => 'required|string|in:done'
+        ]);
+        $now = date('Y-m-d H:i:s');
+        DB::table('cp_subscribe_month_statistic_data')
+            ->where(['id' => $request->input('id'), 'final_state' => 'notCheck'])
+            ->update([
+                'final_state' => $request->input('final_state'),
+                'final_time' => $now,
+                'updated_at' => $now,
+            ]);
+        return 'ok';
+    }
+
+    /**
+     * 导出某个cp某个月的各个书籍的应结算金额
+     * @param Request $request
+     * @return \Illuminate\Support\Collection
+     * @throws \Illuminate\Validation\ValidationException
+     */
+    public function listCpMonthFinalAmount(Request $request) {
+        $this->validate($request, [
+            'cp_name' => 'required|string',
+            'month' => 'required|date_format:Y-m'
+        ]);
+        $cpName = $request->input('cp_name');
+        $cpName = $this->getUserCpName() ?? $cpName;
+        return DB::table('cp_book_month_final_amounts as mfa')
+            ->leftJoin('books', 'books.id', 'mfa.bid')
+            ->where([
+                'mfa.is_enabled' => 1,
+                'mfa.cp_name' => $cpName,
+                'mfa.month' => $request->input('month')
+            ])
+            ->select('mfa.id', 'mfa.bid', 'books.name as book_name', 'mfa.final_amount', 'mfa.cp_name','mfa.month')
+            ->get();
+
+
+    }
+}

+ 63 - 0
modules/CpManage/Http/Controllers/UserTrait.php

@@ -0,0 +1,63 @@
+<?php
+/**
+ * ${CARET}
+ * @file:${FILE_NAME}
+ * @Created by gnitif
+ * @Date: 2023/5/6
+ * @Time: 16:01
+ */
+
+
+namespace Modules\CpManage\Http\Controllers;
+
+use Illuminate\Support\Collection;
+use Illuminate\Support\Facades\DB;
+use Modules\User\Models\User;
+
+trait UserTrait
+{
+    // 当前登录用户
+    protected $currentUser;
+
+    /**
+     * 获取当前登录用户
+     * @return User
+     */
+    protected function getCurrentUser(): User {
+        if(!$this->currentUser) {
+            $this->currentUser = $this->getLoginUser();
+        }
+        return $this->currentUser;
+    }
+    /**
+     * 当前用户的所有的角色标识的结合
+     * @return Collection
+     */
+    protected function listUserRoles():Collection {
+        return $this->getCurrentUser()->roles->pluck('identify');
+    }
+
+    /**
+     * 当前用户是否是cp角色
+     * @return bool
+     */
+    public function userIsCp():bool {
+        return $this->listUserRoles()->contains('cp');
+    }
+
+    /**
+     * 如果当前用户是cp角色,返回cp_name,否则返回null
+     * @return string
+     */
+    public function getUserCpName():string|null {
+        if($this->userIsCp()) {
+            return DB::table('user_belong_to_cp')
+                ->where([
+                    'is_enabled' => 1,
+                    'user_id' => $this->getCurrentUser()->id,
+                ])->value('cp_name');
+        } else {
+            return null;
+        }
+    }
+}

+ 53 - 0
modules/CpManage/Http/Requests/CpRequest.php

@@ -0,0 +1,53 @@
+<?php
+/**
+ * ${CARET}
+ * @file:${FILE_NAME}
+ * @Created by gnitif
+ * @Date: 2023/5/6
+ * @Time: 15:16
+ */
+
+
+namespace Modules\CpManage\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+use Modules\CpManage\Models\Cp\Cps;
+
+class CpRequest extends  FormRequest
+{
+
+    /**
+     * rules
+     *
+     * @return array
+     */
+    public function rules(): array
+    {
+        return [
+            'cp_name' => sprintf('required|unique:%s,%s,%s', Cps::class, 'cp_name', $this->get('cp_id')),
+            "cp_company" =>  "|required|string|min:1",
+            "cp_nick" =>  "|required|string|min:1",
+            "share_per" =>  "|required|Integer|min:0|max:100",
+            // "share_per_before" =>  "|required|Integer|min:1|max:100",
+            // "share_per_after" =>  "|required|Integer|min:1|max:100",
+        ];
+    }
+    /**
+     * messages
+     *
+     * @return string[]
+     */
+    public function messages(): array
+    {
+        return [
+            'cp_name.required' => 'cp名称必须填写',
+            'cp_name.unique' => 'cp名称已存在',
+            'cp_company' => '所属公司必填',
+            'cp_nick' => 'cp简称必填',
+            'address' => '公司地址必填',
+            "share_per" => "分成比例不正确",
+            "share_per_before" => "分成比例不正确",
+            "share_per_after" => "分成比例不正确",
+        ];
+    }
+}

+ 32 - 0
modules/CpManage/Installer.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace Modules\CpManage;
+
+use Catch\Support\Module\Installer as ModuleInstaller;
+use Modules\CpManage\Providers\CpManageServiceProvider;
+
+class Installer extends ModuleInstaller
+{
+    protected function info(): array
+    {
+        // TODO: Implement info() method.
+        return [
+            'title' => 'cp管理',
+            'name' => 'cpManage',
+            'path' => 'cpManage',
+            'keywords' => 'cp管理',
+            'description' => '短剧平台cp管理模块',
+            'provider' =>CpManageServiceProvider::class,
+        ];
+    }
+
+    protected function requirePackages(): void
+    {
+        // TODO: Implement requirePackages() method.
+    }
+
+    protected function removePackages(): void
+    {
+        // TODO: Implement removePackages() method.
+    }
+}

+ 34 - 0
modules/CpManage/Middlewares/CpManageGate.php

@@ -0,0 +1,34 @@
+<?php
+/**
+ * ${CARET}
+ * @file:${FILE_NAME}
+ * @Created by gnitif
+ * @Date: 2023/5/6
+ * @Time: 16:38
+ */
+
+
+namespace Modules\CpManage\Middlewares;
+
+use Illuminate\Http\Request;
+use Modules\Permissions\Exceptions\PermissionForbidden;
+use Modules\User\Models\User;
+
+class CpManageGate
+{
+    public function handle(Request $request, \Closure $next)
+    {
+        if ($request->isMethod('get')) {
+            return $next($request);
+        }
+
+        /* @var User $user */
+        $user = $request->user(getGuardName());
+
+        if (! $user->can()) {
+            throw new PermissionForbidden();
+        }
+
+        return $next($request);
+    }
+}

+ 13 - 0
modules/CpManage/Models/Cp/CpCollection.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace Modules\CpManage\Models\Cp;
+
+use Modules\Common\Models\BaseModel;
+
+class CpCollection extends BaseModel
+{
+    protected $table = 'cp_collections';
+    protected $dates = [];
+    protected $forceDeleting = true;
+    protected $fillable = ['cp_id','cp_name','spider_status','spider_result','created_at', 'updated_at'];
+}

+ 11 - 0
modules/CpManage/Models/Cp/CpSubscribeStatisticDataModel.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace Modules\CpManage\Models\Cp;
+
+use Illuminate\Database\Eloquent\Model;
+
+class CpSubscribeStatisticDataModel extends Model
+{
+    protected $table = 'cp_subscribe_statistic_data';
+    protected $guarded = [];
+}

+ 81 - 0
modules/CpManage/Models/Cp/Cps.php

@@ -0,0 +1,81 @@
+<?php
+/**
+ *cp管理
+ * @file:Cps.php
+ * @Created by gnitif
+ * @Date: 2023/3/20
+ * @Time: 13:57
+ */
+
+
+namespace Modules\CpManage\Models\Cp;
+
+use Catch\Exceptions\FailedException;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Facades\DB;
+use Modules\ContentManage\Services\CpManage\CpService;
+
+class Cps extends Model
+{
+    protected $table = "cps";
+    protected $primaryKey = "cp_id";
+    protected $fillable = [
+        'cp_id', 'cp_nick', 'cp_name', 'cp_company', 'manager', 'phone', 'email', 'share_per', 'settlement_type', 'address', 'is_deleted', 'created_at', 'updated_at', 'deleted_at',
+    ];
+    protected array $fields = ['cp_id', 'cp_nick', 'cp_name', 'cp_company', 'manager', 'phone', 'email', 'share_per','address', 'created_at', 'updated_at'];
+    protected array $form =  ['cp_nick',  'cp_name',  'cp_company',  'manager',  'phone',  'email',  'settlement_type','share_per',   'address'];
+
+    public function storeBy(array $data): mixed
+    {
+        DB::beginTransaction();
+        try {
+            if ($this->create($this->filterData($data))){
+                DB::commit();
+                return  $this->getKey();
+            }else{
+                throw new \Exception("添加失效");
+            }
+
+        }catch (\Exception $exception){
+            DB::rollBack();
+            throw new FailedException('添加失败!请刷新重试');
+        }
+        return false;
+    }
+
+    public function updateBy($id, array $data)
+    {
+
+        $updated = $this->where($this->getKeyName(), $id)->update($this->filterData($data));
+        return $updated;
+    }
+
+    public function deleteBy($id)
+    {
+        $this->where($this->getKeyName(), $id)->update(['is_deleted' => 1,'deleted_at' => date("Y-m-d H:i:s")]);
+    }
+
+    protected function filterData(array $data): array
+    {
+        // 表单保存的数据集合
+        $fillable = array_unique(array_merge($this->getFillable(), property_exists($this, 'form') ? $this->form : []));
+
+        foreach ($data as $k => $val) {
+            if (is_null($val) || (is_string($val) && ! $val)) {
+                unset($data[$k]);
+            }
+
+            if (! empty($fillable) && ! in_array($k, $fillable)) {
+                unset($data[$k]);
+            }
+
+            if (in_array($k, [$this->getUpdatedAtColumn(), $this->getCreatedAtColumn()])) {
+                unset($data[$k]);
+            }
+        }
+
+        return $data;
+    }
+
+
+}

+ 32 - 0
modules/CpManage/Providers/CpManageServiceProvider.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace Modules\CpManage\Providers;
+
+
+use Catch\Providers\CatchModuleServiceProvider;
+use Modules\CpManage\Middlewares\CpManageGate;
+
+class CpManageServiceProvider extends CatchModuleServiceProvider
+{
+    /**
+     * middlewares
+     *
+     * @return string[]
+     */
+    protected function middlewares(): array
+    {
+        return [CpManageGate::class];
+    }
+
+    /**
+     * route path
+     *
+     * @return string|array
+     */
+    public function moduleName(): string|array
+    {
+        // TODO: Implement path() method.
+        return 'cpManage';
+    }
+}
+

+ 49 - 0
modules/CpManage/Services/CpManage/CpService.php

@@ -0,0 +1,49 @@
+<?php
+/**
+ * ${CARET}
+ * @file:CpService.php
+ * @Created by gnitif
+ * @Date: 2023/3/21
+ * @Time: 20:24
+ */
+
+
+namespace Modules\CpManage\Services\CpManage;
+
+use Illuminate\Contracts\Pagination\LengthAwarePaginator;
+use Illuminate\Support\Facades\DB;
+use Modules\CpManage\Models\Cp\Cps;
+
+class CpService
+{
+
+    public static function selectOptions($cpName = "")
+    {
+        $list = Cps::select('cp_id','cp_name','cp_nick','cp_company');
+        if (!empty($cpName)){
+            $list->where('cp_name','like',"%{$cpName}%");
+        }
+        return $list->get();
+    }
+
+    /**
+     *  查询产品列表
+     * name: getCpList
+     * @param  $where
+     * @param int $pageSize
+     * @return LengthAwarePaginator
+     * date 2023/03/22 20:49
+     */
+    public static function getCpList($where , int $pageSize = 20)
+    {
+        $list =  DB::table('cps')->where($where)->orderBy('cp_id','desc')->paginate($pageSize);
+        if(!$list->isEmpty()){
+            foreach ($list as  $value){
+                $value->book_count = 0;
+            }
+        }
+        return  $list;
+    }
+
+
+}

+ 39 - 0
modules/CpManage/routes/route.php

@@ -0,0 +1,39 @@
+<?php
+
+use Illuminate\Support\Facades\Route;
+use Modules\CpManage\Http\Controllers\CpListController;
+use Modules\CpManage\Http\Controllers\CpSubscribeStatisticDataController;
+
+
+Route::prefix('cpManage')->group(function () {
+    Route::prefix('cp')->group(function () {
+        Route::apiResource('manage/cp_list', CpListController::class);
+        // cp选择项
+        Route::any('options',[CpListController::class,"selectOptions"]);
+        /**
+         * cp结算数据中心
+         */
+        Route::get('subscribeStatisticData/list', [CpSubscribeStatisticDataController::class, 'list']);
+        /**
+         * cp结算数据中心统计数据
+         */
+        Route::get('subscribeStatisticData/listStatistic', [CpSubscribeStatisticDataController::class, 'listStatistic']);
+        /**
+         * cp结算
+         */
+        Route::get('subscribeStatisticData/monthList', [CpSubscribeStatisticDataController::class, 'monthList']);
+        /**
+         * 导出某个cp某个月的各个书籍的应结算金额
+         */
+        Route::get('subscribeStatisticData/listCpMonthFinalAmount', [CpSubscribeStatisticDataController::class, 'listCpMonthFinalAmount']);
+        /**
+         * 修改cp结算状态
+         */
+        Route::post('subscribeStatisticData/saveFinalState',
+            [CpSubscribeStatisticDataController::class, 'saveFinalState']);
+
+        Route::post('test/test1', [TestController::class, 'test1'])->withoutMiddleware(config('catch.route.middlewares'));
+
+        Route::get('cpCollection',[CpListController::class,"cpCollection"])->withoutMiddleware(config('catch.route.middlewares'));
+    });
+});

+ 40 - 0
modules/Manage/Enmus/MiniprogramType.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace Modules\Manage\Enmus;
+
+use Catch\Enums\Enum;
+
+
+enum MiniprogramType: int implements Enum
+{
+    case WEIXIN = 1; // 全部数据
+    case BYTECODE = 2; // 自定义数据
+
+
+    public function value(): int
+    {
+        return match ($this) {
+            self::WEIXIN => 1,
+            self::BYTECODE => 2
+        };
+    }
+
+    public function name(): string
+    {
+        return match ($this) {
+            self::WEIXIN => '微信小程序',
+            self::BYTECODE => '字节小程序',
+        };
+    }
+
+    /**
+     * assert value
+     *
+     * @param int $value
+     * @return bool
+     */
+    public function assert(int $value): bool
+    {
+       return $this->value === $value;
+    }
+}

+ 102 - 0
modules/Manage/Http/Controllers/MiniprogramController.php

@@ -0,0 +1,102 @@
+<?php
+
+namespace Modules\Manage\Http\Controllers;
+
+use Illuminate\Routing\Controller;
+use Illuminate\Http\Request;
+use Modules\Manage\Enmus\MiniprogramType;
+use Modules\Manage\Http\Requests\MiniprogramRequest;
+use Modules\Manage\Http\Requests\MiniprogramUpdateRequest;
+use Modules\Manage\Models\Miniprogram;
+use Log;
+
+class MiniprogramController extends Controller
+{
+
+    public function __construct(protected readonly Miniprogram $miniprogram)
+    {
+        
+    }
+
+    /**
+     * 小程序列表
+     * @param Request $request
+     * @return void
+     */
+    public function index(Request $request)
+    {
+        $name = $request->get('name');
+        $play_name = $request->get('play_name');
+        $company = $request->get('company');
+        $where = [];
+        if($name){
+            $where[] = ['name','like','%'.$name.'%']; 
+        }
+        if($play_name){
+            $where[] = ['play_name','like','%'.$play_name.'%']; 
+        }
+        if($company){
+            $where[] = ['company','like','%'.$company.'%']; 
+        }
+        $result = $this->miniprogram->where($where)->paginate(20);
+        foreach($result as $item){
+            $item->type_name = MiniprogramType::from($item->type)->name();
+            $item->status_name = $item->status == 1 ?'启用':'禁用';
+        }
+        return $result;
+    }
+
+    /**
+     * 添加小程序
+     *
+     * @param MiniprogramRequest $request
+     * @return void
+     */
+    public function store(MiniprogramRequest $request)
+    {
+        $validate_result = $request->validated();
+        $validate_result['remark'] = $request->post('remark','') ?? '';
+        return $this->miniprogram->create($validate_result)->toArray();
+
+    }
+
+    /**
+     * 小程序详情
+     *
+     * @param [type] $id
+     * @return void
+     */
+    public function show($id)
+    {
+        return $this->miniprogram->find($id)->toArray();
+    }
+
+    /**
+     * 更新小程序
+     *
+     * @param [type] $id
+     * @param MiniprogramUpdateRequest $request
+     * @return void
+     */
+    public function update($id, MiniprogramUpdateRequest $request)
+    {
+        $validate_result = $request->validated();
+        if($request->post('remark','')){
+            $validate_result['remark'] = $request->post('remark','');
+        }
+        $this->miniprogram->where('id',$id)->update($validate_result);
+        return [];
+    }
+
+
+    /**
+     * 小程序类型列表
+     *
+     * @return array [ ['name'=>'微信小程序','id'=>1],[],[] ]
+     */
+    public function typeList(){
+        $type_list =  MiniprogramType::cases();
+        $data = array_map( fn($item)=>['name'=>$item->name(),'value'=>$item->value()],$type_list );
+        return $data;
+    }
+}

+ 115 - 0
modules/Manage/Http/Controllers/UserMiniprogramController.php

@@ -0,0 +1,115 @@
+<?php
+
+namespace Modules\Manage\Http\Controllers;
+
+use Catch\Base\CatchController;
+use Illuminate\Http\Request;
+use Modules\Channel\Models\UserHasMiniprograms;
+use Modules\Channel\Services\User\UserService;
+use Modules\Channel\Exceptions\ChannelBusinessException;
+use Modules\Common\Errors\Errors;
+use Modules\Manage\Models\Miniprogram;
+use Log;
+
+class UserMiniprogramController extends CatchController
+{
+
+    const  COMPANY_ROLE = 'company';
+    public function __construct(
+        protected readonly UserHasMiniprograms $userHasMiniprograms,
+        protected readonly Miniprogram $miniprogram
+        )
+    {
+        
+    }
+
+
+    /**
+     * 绑定小程序和投放公司的关系
+     * @param [type] $miniprogram_id 
+     * @param Request $request  uid=2,3,4,5 actison=on|off on:分配,off取消分配
+     * @return array
+     * 
+     */
+    public function allocationStore($miniprogram_id,Request $request)
+    {
+        $uids  = $request->post('uids');
+        $action = $request->post('action');
+        if(empty($miniprogram_id) || empty($uids) || empty($action) || !in_array($action,['on','off'])){
+            ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
+        }
+
+        $miniprogram_info =  $this->miniprogram->find($miniprogram_id);
+        if(!$miniprogram_info || $miniprogram_info->status == 0){
+            ChannelBusinessException::throwError(Errors::MINIPROGRAM_STATUS_ERROR);
+        }
+
+        return collect(explode(',',$uids))->filter(function (int $value, int $key) use($miniprogram_id,$action){
+            $user_access = UserService::userHasRole($value,self::COMPANY_ROLE);
+            //只能分配给投手公司
+            if($user_access){
+                $result = $this->userHasMiniprograms->where('uid',$value)->where('miniprogram_id',$miniprogram_id)->first();
+                if($action == 'off'){
+                    if($result){
+                        $result->is_enabled = 0;
+                        $result->save();
+                    }
+                    return true;
+                }
+                if($result){
+                    if($result->is_enabled == 0){
+                        $result->is_enabled = 1;
+                        $result->save();
+                    }
+                    return true;
+                }
+                $this->userHasMiniprograms->create([
+                    'uid'=>$value,'miniprogram_id'=>$miniprogram_id,'is_enabled'=>1
+                ]);
+                return true;
+            }
+            return false;
+        });
+
+    }
+
+
+    /**
+     * 获取投手公司和小程序的绑定关系,用于前端数据回显
+     * @param [type] $miniprogram_id
+     * @return []
+     * response = [
+     *      'on'=>[ ['id'=>1,'username'=>'公司1','user_has_miniprogram'=>1],[]  ],
+     *      'off'=>[['id'=>1,'username'=>'公司1','user_has_miniprogram'=>0],[]],
+     *      'all'=>[ 
+     *          ['id'=>1,'username'=>'公司1','user_has_miniprogram'=>1],
+     *          ['id'=>2,'username'=>'公司1','user_has_miniprogram'=>0] 
+     *          ]
+     *      ]
+     * 
+     */
+    public function getAllocationInfo($miniprogram_id){
+        $all_company_account = UserService::listByRole(self::COMPANY_ROLE,['users.username','users.id']);
+        $result = $all_company_account->map(function ($item,$key) use($miniprogram_id) {
+            $info = $this->userHasMiniprograms->where('uid',$item->id)->where('miniprogram_id',$miniprogram_id)->where('is_enabled',1)->count();
+            if($info){
+                $item->user_has_miniprogram = 1;
+                $item->user_has_miniprogram_flag = 'on';
+            }else{
+                $item->user_has_miniprogram = 0;
+                $item->user_has_miniprogram_flag = 'off';
+            }
+            return $item;
+        });
+        $group = $result->groupBy('user_has_miniprogram_flag')->toArray();
+        if(!isset($group['on'])){
+            $group['on'] = [];
+        }
+        if(!isset($group['off'])){
+            $group['off'] = [];
+        }
+        $group['all'] = $result->toArray();
+        return $group;
+    }
+
+}

+ 53 - 0
modules/Manage/Http/Requests/MiniprogramRequest.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace Modules\Manage\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+use Modules\Manage\Enmus\MiniprogramType;
+use Illuminate\Validation\Rule;
+
+class MiniprogramRequest extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     */
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
+     */
+    public function rules(): array
+    {
+        return [
+            'name'=> 'required|max:50',
+            'play_name'=> 'required|max:100',
+            'company'=> 'required|max:255',
+            'type'=> [
+                'required',
+                Rule::in( array_map( fn($item)=>$item->value(),MiniprogramType::cases())),
+            ],
+            'appsecret'=>'required|min:30|max:64',
+            'appid'=>'required|unique:miniprogram|min:18|max:32',
+            'status'=>'in:0,1'
+        ];
+    }
+
+
+    public function messages()
+    {
+        return [
+            'name.required'=>'小程序名称必填',
+            'appid.min'=>'appid太短',
+            'appid.max'=>'appid过长',
+            'appsecret.min'=>'appsecret太短',
+            'appsecret.max'=>'appsecret过长'
+        ];
+    }
+}
+
+

+ 53 - 0
modules/Manage/Http/Requests/MiniprogramUpdateRequest.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace Modules\Manage\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+use Modules\Manage\Enmus\MiniprogramType;
+use Illuminate\Validation\Rule;
+
+class MiniprogramUpdateRequest extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     */
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
+     */
+    public function rules(): array
+    {
+        return [
+            'name'=> 'required|max:50',
+            'play_name'=> 'required|max:100',
+            'company'=> 'required|max:255',
+            'type'=> [
+                'required',
+                Rule::in( array_map( fn($item)=>$item->value(),MiniprogramType::cases())),
+            ],
+            'appsecret'=>'required|min:30|max:64',
+            'appid'=>'required|min:18|max:32',
+            'status'=>'in:0,1'
+        ];
+    }
+
+    
+    public function messages(): array
+    {
+        return [
+            'name.required'=>'小程序名称必填',
+            'appid.min'=>'appid太短',
+            'appid.max'=>'appid过长',
+            'appsecret.min'=>'appsecret太短',
+            'appsecret.max'=>'appsecret过长'
+        ];
+    }
+}
+
+

+ 32 - 0
modules/Manage/Installer.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace Modules\Manage;
+
+use Catch\Support\Module\Installer as ModuleInstaller;
+use Modules\Manage\Providers\ManageServiceProvider;
+
+class Installer extends ModuleInstaller
+{
+    protected function info(): array
+    {
+        // TODO: Implement info() method.
+        return [
+            'title' => '管理模块',
+            'name' => 'manage',
+            'path' => 'manage',
+            'keywords' => '',
+            'description' => '',
+            'provider' => ContentManageServiceProvider::class
+        ];
+    }
+
+    protected function requirePackages(): void
+    {
+        // TODO: Implement requirePackages() method.
+    }
+
+    protected function removePackages(): void
+    {
+        // TODO: Implement removePackages() method.
+    }
+}

+ 30 - 0
modules/Manage/Models/BaseModel.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace Modules\Manage\Models;
+
+use Catch\Base\CatchModel as Model;
+use Illuminate\Database\Eloquent\Builder;
+
+
+abstract class BaseModel extends Model
+{
+
+    protected array $defaultHidden = [];
+
+    protected array $defaultCasts = [
+        'created_at' => 'datetime:Y-m-d H:i:s',
+
+        'updated_at' => 'datetime:Y-m-d H:i:s',
+    ];
+    protected $dateFormat = '';
+
+    public static function bootSoftDeletes(): void{
+
+    }
+
+
+    public function scopeActive(Builder $query): void
+    {
+        $query->where($this->table.'.is_enabled', 1);
+    }
+}

+ 20 - 0
modules/Manage/Models/Miniprogram.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace Modules\Manage\Models;
+
+
+class Miniprogram extends BaseModel
+{
+
+    protected string $sortField = 'id';
+
+    // 排序规则
+    protected bool $sortDesc = true;
+
+    protected $table = 'miniprogram';
+
+    protected $fillable = [
+        'id', 'name', 'company', 'type', 'appid', 'appsecret', 'status', 'remark', 'play_name','created_at', 'updated_at'
+    ];
+
+}

+ 20 - 0
modules/Manage/Providers/ManageServiceProvider.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace Modules\Manage\Providers;
+
+use Catch\CatchAdmin;
+use Catch\Providers\CatchModuleServiceProvider;
+
+class ManageServiceProvider extends CatchModuleServiceProvider
+{
+    /**
+     * route path
+     *
+     * @return string
+     */
+    public function moduleName(): string
+    {
+        // TODO: Implement path() method.
+        return 'manage';
+    }
+}

+ 12 - 0
modules/Manage/config/miniprogram.php

@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * 小程序配置
+ */
+return [
+    
+    'typelist'=>[
+        'WEIXIN','BYTECODE'
+    ],
+    
+];

+ 38 - 0
modules/Manage/routes/route.php

@@ -0,0 +1,38 @@
+<?php
+
+use Illuminate\Support\Facades\Route;
+
+use Modules\Manage\Http\Controllers\MiniprogramController;
+use Modules\Manage\Http\Controllers\UserMiniprogramController;
+
+Route::prefix('manage')->group(function(){
+    Route::prefix('miniprogram')->group(function () {
+        //类型列表
+        Route::get('typelist',[MiniprogramController::class,'typeList'])
+        ->withoutMiddleware(config('catch.route.middlewares'));
+
+        //添加
+        Route::post('store',[MiniprogramController::class,'store'])
+        ->withoutMiddleware(config('catch.route.middlewares'));
+
+        //小程序列表
+        Route::get('index',[MiniprogramController::class,'index'])
+        ->withoutMiddleware(config('catch.route.middlewares'));
+
+        //小程序详情
+        Route::get('show/{id}',[MiniprogramController::class,'show'])
+        ->withoutMiddleware(config('catch.route.middlewares'));
+
+         //小程序详情
+         Route::post('update/{id}',[MiniprogramController::class,'update'])
+         ->withoutMiddleware(config('catch.route.middlewares'));
+
+         //小程序分配列表
+         Route::get('allocation/{miniprogram_id}',[UserMiniprogramController::class,'getAllocationInfo'])
+         ->withoutMiddleware(config('catch.route.middlewares'));
+        //分配小程序
+         Route::post('allocation/{miniprogram_id}',[UserMiniprogramController::class,'allocationStore'])
+         ->withoutMiddleware(config('catch.route.middlewares'));
+
+    });
+});

+ 3 - 1
modules/User/Http/Controllers/AuthController.php

@@ -25,7 +25,9 @@ class AuthController extends Controller
         $user = User::query()->where('email', $request->get('email'))->first();
 
         Event::dispatch(new Login($request, $user));
-
+        if ($user && $user->status != 1){
+            throw new FailedException('账号不存在或已停用!');
+        }
         if ($user && Hash::check($request->get('password'), $user->password)) {
             $token = $user->createToken('token')->plainTextToken;
             return compact('token');

+ 0 - 2
modules/User/Http/Controllers/UserTrait.php

@@ -2,8 +2,6 @@
 
 namespace Modules\User\Http\Controllers;
 
-use Catch\Base\CatchController;
-use Illuminate\Http\Request;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\DB;
 use Modules\Common\Errors\Errors;

+ 1 - 0
modules/User/Models/User.php

@@ -115,6 +115,7 @@ class User extends Model implements AuthenticatableContract
      * 否则展示所有isApp为false以及showApp对应的name的模块
      * @param string $showApp
      */
+    
     public function showPermissions($showApp = '') {
         $hiddenAppModuleNames = Modules::getAppModules()->reject(function ($module) use ($showApp) {
             return $showApp == $module['name'];

+ 1 - 1
modules/Video/Http/Controllers/VideoController.php

@@ -14,8 +14,8 @@ use Modules\Video\Services\VideoService;
 
 class VideoController extends CatchController
 {
-    use UserTrait;
     use ValidatesRequests;
+    use UserTrait;
 
     /**
      * 短剧列表

+ 0 - 9
phpunit.xml

@@ -11,15 +11,6 @@
         <testsuite name="Feature">
             <directory suffix="Test.php">./tests/Feature</directory>
         </testsuite>
-
-        <testsuite name="ContentOutput">
-            <directory suffix="Test.php">./tests/ContentManage/Output</directory>
-        </testsuite>
-
-        <testsuite name="ContentOutputBook">
-            <directory suffix="Test.php">./tests/ContentManage/Http/Controllers</directory>
-        </testsuite>
-
     </testsuites>
     <coverage processUncoveredFiles="true">
         <include>

+ 0 - 27
tests/Common/Http/Controllers/OptionControllerTest.php

@@ -1,27 +0,0 @@
-<?php
-
-namespace Tests\Common\Http\Controllers;
-
-use Modules\Common\Http\Controllers\OptionController;
-use Modules\Common\Support\Trace\TraceContext;
-use PHPUnit\Framework\TestCase;
-
-class OptionControllerTest extends \Tests\TestCase
-{
-
-    public function testIndex()
-    {
-        $res = $this->get('http://localhost/api/options/xiaoming');
-//        $res->dump();
-        dump(app(TraceContext::class)->getTraceInfo());
-        dump(app(TraceContext::class)->getTraceInfo());
-        dump($info1 = app(TraceContext::class)->getTraceInfo());
-        $channel = \Log::build([
-            'driver' => 'daily',
-            'path' => storage_path('logs/aa.log'),
-            'level' => 'debug'
-        ]);
-        \Log::stack([$channel])->info('hellow', ['traceInfo' => $info1]);
-        \Log::stack([$channel])->debug('hellow', ['traceInfo' => $info1]);
-    }
-}

+ 0 - 17
tests/Common/Support/Trace/CustomizeLoggerTest.php

@@ -1,17 +0,0 @@
-<?php
-
-namespace Tests\Common\Support\Trace;
-
-use Modules\Common\Support\Trace\CustomizeLogger;
-use PHPUnit\Framework\TestCase;
-
-class CustomizeLoggerTest extends \Tests\TestCase
-{
-
-    public function testGetSubscribeLogger()
-    {
-        $logger = CustomizeLogger::getSubscribeLogger();
-        $logger->debug('dddd', ['kk' => 1]);
-        $logger->info('dddd', ['kk' => 1]);
-    }
-}

+ 0 - 97
tests/ContentManage/Http/Controllers/BookControllerTest.php

@@ -1,97 +0,0 @@
-<?php
-
-namespace Tests\ContentManage\Http\Controllers;
-
-use Illuminate\Foundation\Testing\RefreshDatabase;
-use Illuminate\Foundation\Testing\WithFaker;
-use Illuminate\Support\Facades\Storage;
-use Illuminate\Http\UploadedFile;
-use Tests\TestCase;
-
-class BookControllerTest extends TestCase
-{
-    /**
-     * A basic feature test example.
-     */
-    public function test_book_import(): void
-    {
-    $content = <<<EOT
-###第一章 前女友居然会逆袭
-大学毕业之后在武汉呆了半年,楚飞终于还是决定去深圳。
-之所以会做出这个决定,倒不是因为什么其它什么乱七八糟的理由,简单四个字,人穷志短!
-同样是刚刚毕业半年,楚飞现在每个月拿着不到两千块的工资勉强活着,但他的女朋友李冉却每个月可以拿四千的固定工资,而且刚刚发放的年底奖金,她竟然拿了十五万!这样折合起来她一个月接近一万七八千的薪水了,是楚飞的十倍!
-这就是差距
-###第二章 发光的残破青铜壶
-所以兜兜转转一圈之后,终于还是回到了原点么?
-
-现在承受着楚飞凶猛冲刺的不是他以为这辈子最爱的女人李冉,而是前女友张倩,一个对性爱无比热情无比投入的女人,偏偏也只有她这样的女人才能让楚飞玩的尽兴,玩的爽快,这还真是一件很搞笑的事情。因为在张倩身上楚飞可以不用压抑自己,更不用委屈自己,他想用什么姿势玩都行,想用多大的力道都行,甚至……想射在她身体上的任何位置都没问题!
-
-而在李冉身上,这一切永远只是奢望。
-
-###第三章 吃不饱的恐怖怪物
-楚飞先回宿舍去洗了个澡,然后收拾了一下自己的东西,准备踏踏实实的定下心干活。
-###第四章 妹是用来调教的
-楚飞真的愕住了,是真的。
-他从没有想过,那个自小时候就喜欢粘着他不停问问题的丫头,每次被他逗几句就会脸红心跳的诗诗丫头,来了深圳四年之后,却已经变成了这样……时间果然是一把残忍的杀猪刀,而现实也最是无情的恶魔,多少的美好都已经随风彻底的逝去。
-轻轻的走上去,楚飞在何诗诗的屁股上轻轻拍了拍,然后帮她拉起了内裤,“诗诗,我不是要跟你……”
-###第五章 男人应该胸有成竹
-发泄过后的男人总会有一阵空虚感,不过看着表妹把自己爆发出的东西一点不剩的全都吞了下去,楚飞突然却又觉得很有一种成就感。
-她……是我表妹呀!!
-EOT;
-        $file = UploadedFile::fake()->createWithContent("美女养成师.txt",$content);
-        $response = $this->postJson("api/contentManage/book/import",[
-            'cp_id'=>1,
-            'cp_name'=>'Testcp01111',
-            'book_name'=>'美女养成师师',
-            'author'=>'小林',
-            'channel'=>1,
-            'category_id'=>21,
-            'category_name'=>'武侠仙侠',
-            'vip_start'=>4,
-            'file'=>$file
-        ]);
-        print_r(json_decode($response->getContent(),1));   
-        $response->assertStatus(200);
-    }
-
-
-    public function test_create_book(): void
-    {
-        $path = 'book/NqpYgFL6yddDPSOnAwhIihk0DRjO7hEbOY3geJ6s.txt';
-        $response = $this->postJson("api/contentManage/book/createBook",[
-            'cp_id'=>1,
-            'cp_name'=>'Testcp01111',
-            'book_name'=>'美女养成的师师',
-            'author'=>'小林',
-            'channel'=>1,
-            'category_id'=>21,
-            'category_name'=>'武侠仙侠',
-            'vip_start'=>4,
-            'path'=>$path
-        ]);
-        print_r(json_decode($response->getContent(),1));   
-        $response->assertStatus(200);
-    }
-
-    
-    private $token;
-    protected function setUp(): void
-    {
-        parent::setUp(); // TODO: Change the autogenerated stub
-        $tokenInfo = $this->post('http://localhost/api/login', [
-            'email' => 'catch@admin.com',
-            'password' => 'catchadmin',
-            'remember' => false
-        ])->json();
-        $this->token = $tokenInfo['data']['token'];
-    }
-
-
-    public function testList()
-    {
-        $res = $this->withHeaders([
-            'Authorization' => 'Bearer '. $this->token,
-        ])->json('get', 'http://localhost/api/contentManage/book/list?is_export=1');
-        $res->dump();
-    }
-}

+ 0 - 22
tests/ContentManage/Http/Controllers/CpListControllerTest.php

@@ -1,22 +0,0 @@
-<?php
-
-namespace Tests\ContentManage\Http\Controllers;
-
-use Illuminate\Foundation\Testing\RefreshDatabase;
-use Illuminate\Foundation\Testing\WithFaker;
-use Illuminate\Support\Facades\Storage;
-use Illuminate\Http\UploadedFile;
-use Tests\TestCase;
-
-// php artisan test --testsuite=ContentOutputBook
-
-class CpListControllerTest extends TestCase{
-
-    public function test_cpP_collection(){
-
-        $response = $this->getJson("api/contentManage/cp/cpCollection?cp_id=1&cp_name=Testcp01111");
-        print_r(json_decode($response->getContent(),1));   
-        $response->assertStatus(200);
-
-    }
-}

+ 0 - 62
tests/ContentManage/Http/Controllers/CpSubscribeStatisticDataControllerTest.php

@@ -1,62 +0,0 @@
-<?php
-
-namespace Tests\ContentManage\Http\Controllers;
-
-use Modules\ContentManage\Http\Controllers\CpSubscribeStatisticDataController;
-use PHPUnit\Framework\TestCase;
-
-class CpSubscribeStatisticDataControllerTest extends \Tests\UsedTestCase
-{
-    public function testList()
-    {
-        $res = $this->withHeaders([
-            'Authorization' => 'Bearer '. $this->token,
-        ])->json('get','http://localhost/api/contentManage/cp/subscribeStatisticData/list?'.http_build_query([
-                'limit' => 15, 'page' => 1, 'book_name' => '小溪村的诱惑',
-                'cp_name' => 'quyuewang'
-            ]));
-        dump(\json_encode($res->json()));
-        $res->dump();
-    }
-
-    public function testlistStatistic()
-    {
-        $res = $this->withHeaders([
-            'Authorization' => 'Bearer '. $this->token,
-        ])->json('get','http://localhost/api/contentManage/cp/subscribeStatisticData/listStatistic?');
-        dump(\json_encode($res->json()));
-        $res->dump();
-    }
-
-    public function testMonthList()
-    {
-        $res = $this->withHeaders([
-            'Authorization' => 'Bearer '. $this->token,
-        ])->json('get','http://localhost/api/contentManage/cp/subscribeStatisticData/monthList?'.http_build_query([
-                'limit' => 15, 'page' => 1 , 'month' => '2022-07', 'cp_name' => 'Testcp01111'
-            ]));
-        dump(\json_encode($res->json()));
-        $res->dump();
-    }
-
-    public function testSaveFinalState() {
-        $res = $this->withHeaders([
-            'Authorization' => 'Bearer '. $this->token,
-        ])->json('post','http://localhost/api/contentManage/cp/subscribeStatisticData/saveFinalState', [
-            'id' => 1, 'final_state' => 'done'
-        ]);
-        dump(\json_encode($res->json()));
-        $res->dump();
-    }
-
-    public function testlistCpBooksMonthFinalAmount() {
-        $res = $this->withHeaders([
-            'Authorization' => 'Bearer '. $this->token,
-        ])->json('get','http://localhost/api/contentManage/cp/subscribeStatisticData/listCpMonthFinalAmount?'.http_build_query([
-                'cp_name' => '1221', 'month' => '2023-03'
-            ]));
-
-        $this->dumpJson($res);
-    }
-
-}

+ 0 - 57
tests/ContentManage/Output/OutputTest.php

@@ -1,57 +0,0 @@
-<?php
-
-namespace Tests\ContentManage\Output;
-
-// use Illuminate\Foundation\Testing\RefreshDatabase;
-use Tests\TestCase;
-
-/**
- * 输出测试
- */
-class OutputTest extends TestCase
-{
-    private string $query = 'channel_name=zhuishuyun&channel_key=123456';
-    private string $prefix = '/api/output/';
-    /**
-     * 
-     *书籍列表
-     * @return void
-     */
-    public function test_book_list()
-    {
-        $response = $this->getJson($this->prefix.'booklist?'.$this->query);
-        print_r(json_decode($response->getContent(),1));    
-        $response->assertStatus(200);
-    }
-
-    public function test_book_detail()
-    {
-        $response = $this->getJson($this->prefix.'bookdetail/1?'.$this->query);
-        print_r(json_decode($response->getContent(),1));   
-        $response->assertStatus(200);
-    }
-
-    public function test_chapter_list()
-    {
-        $response = $this->getJson($this->prefix.'chapterlist/1?'.$this->query);
-        //print_r(json_decode($response->getContent(),1));   
-        $response->assertStatus(200);
-    }
-
-
-
-    public function test_chapter_content()
-    {
-        $response = $this->getJson($this->prefix.'chaptercontent/1/chapterid/1?'.$this->query);
-        print_r(json_decode($response->getContent(),1));
-        $response->assertStatus(200)->assertJsonPath('code', 10000);
-    }
-
-
-    public function test_categories()
-    {
-        $response = $this->getJson($this->prefix.'listCategories?'.$this->query);
-        print_r(json_decode($response->getContent(),1));
-        $response->assertStatus(200)->assertJsonPath('code', 10000);
-    }
-}

+ 0 - 18
tests/ContentManage/Services/CP/SyncSubscribeTest.php

@@ -1,18 +0,0 @@
-<?php
-
-namespace Tests\ContentManage\Services\CP;
-
-use Modules\ContentManage\Services\CpManage\SyncSubscribe;
-use PHPUnit\Framework\TestCase;
-
-class SyncSubscribeTest extends \Tests\TestCase
-{
-    public function testsync() {
-        $syncSubscribe = new SyncSubscribe();
-        $syncSubscribe->syncUrl = 'http://pubapi.pre.aizhuishu.com/outapi/zhiyu/getSubsByZhiyu';
-        $syncSubscribe->syncStartDate = '2022-07-25';
-        $syncSubscribe->syncEndDate = '2022-07-26';
-
-        $syncSubscribe->sync();
-    }
-}

+ 0 - 52
tests/ContentManage/Services/CpManage/BookSettlementTest.php

@@ -1,52 +0,0 @@
-<?php
-
-namespace Tests\ContentManage\Services\CpManage;
-
-use Illuminate\Support\Facades\DB;
-use Modules\Common\Support\Trace\TraceContext;
-use Modules\ContentManage\Services\CpManage\BookSettlement;
-use PHPUnit\Framework\TestCase;
-
-class BookSettlementTest extends \Tests\TestCase
-{
-    private $bid = 10002;
-    protected function setUp11(): void
-    {
-        parent::setUp(); // TODO: Change the autogenerated stub
-
-        $startDate = '2023-01-23';
-        $endDate = '2023-05-13';
-
-        $date = $startDate;
-        DB::table('cp_subscribe_statistic_data')
-            ->where(['bid' => $this->bid])
-            ->delete();
-        while ($date <= $endDate) {
-            $nextDate = date_add(date_create($date), date_interval_create_from_date_string('1 day'))->format('Y-m-d');
-            DB::table('cp_subscribe_statistic_data')
-                ->insert([
-                    'bid' => $this->bid,
-                    'calculate_date' => $nextDate,
-                    'settlement_date' => $date,
-                    'month' => date_create($date)->format('Y-m'),
-                    'cp_name' => 'kanshu',
-                    'yesterday_available_amount' => rand(1000 , 5000),
-                    'yesterday_final_amount' => rand(100, 500),
-                    'yesterday_total_coins' => rand(10000, 50000),
-                    'book_settlement_type' => array_rand(['share', 'bottomline', 'buyout'])
-                ]);
-            $date = $nextDate;
-        }
-
-    }
-
-    public function testRun()
-    {
-        $bid = 10002;
-        $month = '2023-03';
-        dump($pInfo = app(TraceContext::class)->getTraceInfo());
-        $service = new BookSettlement($bid, $month);
-        $service->traceContext = TraceContext::newFromParent($pInfo);
-        dump($service->detail());
-    }
-}

+ 1 - 1
tests/Feature/ExampleTest.php

@@ -12,7 +12,7 @@ class ExampleTest extends TestCase
      *
      * @return void
      */
-    public function test_the_application_returns_a_successful_response()
+    public function ttest_the_application_returns_a_successful_response()
     {
         $response = $this->get('/');
 

+ 65 - 0
tests/Feature/MiniprogramTest.php

@@ -0,0 +1,65 @@
+<?php
+
+namespace Tests\Feature;
+
+use Illuminate\Foundation\Testing\RefreshDatabase;
+use Illuminate\Foundation\Testing\WithFaker;
+use Tests\TestCase;
+
+class MiniprogramTest extends TestCase
+{
+    /**
+     * php artisan test --testsuite=Feature
+     * A basic feature test example.
+     */
+    public function ttest_example(): void
+    {
+        $response = $this->getJson('/api/manage/miniprogram/allocation/13');
+        //$response = $this->getJson('/api/manage/miniprogram/index');
+
+        echo $response->getContent();
+    }
+
+
+    public function  ttest_store(): void
+    {
+        /*
+        $response = $this->postJson('/api/channel/paytemplate/update/5',[
+            'name'=>'AAAA模板11',
+            'status'=>'0',
+            'options'=>'[{"price":9,"type":"FIRST_COIN","given":1000,"sequence":1,"is_default":0},{"price":30,"type":"COIN","given":0,"sequence":2,"is_default":1},{"price":50,"type":"COIN","given":4000,"sequence":3,"is_default":1},{"price":190,"type":"MONTH","given":0,"sequence":4,"is_default":1},{"price":290,"type":"YEAR","given":0,"sequence":5,"is_default":0}]'
+        ]);*/
+
+
+        $response = $this->postJson('/api/channel/paytemplate/updatePayTemplateItem/31',[
+            'price'=>10,'type'=>'FIRST_COIN','given'=>1000,'is_default'=>1
+        ]);
+
+        //$response = $this->postJson('/api/channel/paytemplate');
+
+        echo $response->getContent();
+
+        $response->dd();
+    }
+
+
+    public function ttest_allocation(): void
+    {
+        $response = $this->postJson('/api/manage/miniprogram/allocation/17',[
+            'uids'=>'2,5',
+            'action'=>'on'
+        ]);
+
+        $response->dd();
+    }
+
+
+    public function test_index(): void
+    {
+        $name = '亿';
+        $response = $this->getJson('/api/channel/paytemplate/optionSequence');
+        //$response = $this->getJson('/api/channel/paytemplate/optionSequence');
+        echo $response->getContent();
+        $response->dd();
+    }
+}

+ 0 - 18
tests/Unit/ExampleTest.php

@@ -16,22 +16,4 @@ class ExampleTest extends TestCase
     {
         $this->assertTrue(true);
     }
-
-    public function testmyLog() {
-        myLog('test1111')->info('kkkkk');
-    }
-
-    public function testDate() {
-        $str = 'php artisan ContentManage:SyncCpSubscribeStatisticDataFromZW --startDate=%s --endDate=%s';
-
-        $startDate = '2023-04-01';
-        $newStr = '';
-        foreach (range(1, 32) as $i) {
-            $endDate = date_add(date_create($startDate), date_interval_create_from_date_string('1 day'))->format('Y-m-d');
-//            dump(sprintf($str, $startDate, $endDate));
-            $newStr .= sprintf($str, $startDate, $endDate) . "\r\n";
-            $startDate = $endDate;
-        }
-        dump($newStr);
-    }
 }