mengmeng 3 years ago
commit
54cc100d8f
100 changed files with 5707 additions and 0 deletions
  1. 18 0
      .editorconfig
  2. 52 0
      .env.example
  3. 72 0
      .env.online
  4. 5 0
      .gitattributes
  5. 15 0
      .gitignore
  6. 14 0
      .styleci.yml
  7. 66 0
      README.md
  8. 25 0
      app/Admin/Actions/Grid/CouponSetAction.php
  9. 29 0
      app/Admin/Actions/Grid/GiftBoxHitAction.php
  10. 27 0
      app/Admin/Actions/Grid/LevelPasterAction.php
  11. 26 0
      app/Admin/Actions/Grid/LevelPercentAction.php
  12. 29 0
      app/Admin/Actions/Grid/NewUserCouponAction.php
  13. 25 0
      app/Admin/Actions/Grid/PackRecordAction.php
  14. 92 0
      app/Admin/Controllers/AccountController.php
  15. 170 0
      app/Admin/Controllers/AttireController.php
  16. 9 0
      app/Admin/Controllers/AuthController.php
  17. 162 0
      app/Admin/Controllers/BoxRecordController.php
  18. 110 0
      app/Admin/Controllers/ConfigController.php
  19. 133 0
      app/Admin/Controllers/CouponRecordController.php
  20. 117 0
      app/Admin/Controllers/FittingRoomController.php
  21. 118 0
      app/Admin/Controllers/GiftBoxController.php
  22. 129 0
      app/Admin/Controllers/GiftController.php
  23. 113 0
      app/Admin/Controllers/GiftPackController.php
  24. 111 0
      app/Admin/Controllers/GiftRecordController.php
  25. 36 0
      app/Admin/Controllers/HomeController.php
  26. 85 0
      app/Admin/Controllers/LiveRoomController.php
  27. 74 0
      app/Admin/Controllers/PackRecordController.php
  28. 132 0
      app/Admin/Controllers/PasterRecordController.php
  29. 69 0
      app/Admin/Controllers/ResourceController.php
  30. 74 0
      app/Admin/Forms/CouponSet.php
  31. 63 0
      app/Admin/Forms/GiftBoxHit.php
  32. 69 0
      app/Admin/Forms/LevelPaster.php
  33. 77 0
      app/Admin/Forms/LevelPercent.php
  34. 62 0
      app/Admin/Forms/NewUserCoupon.php
  35. 100 0
      app/Admin/Metrics/Examples/NewDevices.php
  36. 108 0
      app/Admin/Metrics/Examples/NewUsers.php
  37. 114 0
      app/Admin/Metrics/Examples/ProductOrders.php
  38. 117 0
      app/Admin/Metrics/Examples/Sessions.php
  39. 116 0
      app/Admin/Metrics/Examples/Tickets.php
  40. 129 0
      app/Admin/Metrics/Examples/TotalUsers.php
  41. 55 0
      app/Admin/Renderable/AttireTable.php
  42. 48 0
      app/Admin/Renderable/BoxRecordAttiresTable.php
  43. 48 0
      app/Admin/Renderable/BoxRecordRetrieveAttiresTable.php
  44. 52 0
      app/Admin/Renderable/BoxRecordTable.php
  45. 47 0
      app/Admin/Renderable/GiftRecordTable.php
  46. 53 0
      app/Admin/Renderable/GiftTable.php
  47. 48 0
      app/Admin/Renderable/PackRecordTable.php
  48. 16 0
      app/Admin/Repositories/Account.php
  49. 16 0
      app/Admin/Repositories/Attire.php
  50. 16 0
      app/Admin/Repositories/BoxRecord.php
  51. 16 0
      app/Admin/Repositories/Config.php
  52. 16 0
      app/Admin/Repositories/CouponRecord.php
  53. 16 0
      app/Admin/Repositories/FittingRoom.php
  54. 16 0
      app/Admin/Repositories/Gift.php
  55. 16 0
      app/Admin/Repositories/GiftBox.php
  56. 16 0
      app/Admin/Repositories/GiftPack.php
  57. 16 0
      app/Admin/Repositories/GiftRecord.php
  58. 16 0
      app/Admin/Repositories/LiveRoom.php
  59. 16 0
      app/Admin/Repositories/PackRecord.php
  60. 16 0
      app/Admin/Repositories/PasterRecord.php
  61. 16 0
      app/Admin/Repositories/Resource.php
  62. 28 0
      app/Admin/bootstrap.php
  63. 29 0
      app/Admin/routes.php
  64. 126 0
      app/Console/Commands/SyncOss.php
  65. 59 0
      app/Console/Commands/TruncateUserDataCommand.php
  66. 32 0
      app/Console/Kernel.php
  67. 41 0
      app/Exceptions/Handler.php
  68. 213 0
      app/Http/Controllers/AccountController.php
  69. 174 0
      app/Http/Controllers/AuthController.php
  70. 283 0
      app/Http/Controllers/BoxController.php
  71. 30 0
      app/Http/Controllers/CommonController.php
  72. 13 0
      app/Http/Controllers/Controller.php
  73. 43 0
      app/Http/Controllers/CouponController.php
  74. 121 0
      app/Http/Controllers/FittingRoomController.php
  75. 177 0
      app/Http/Controllers/GiftController.php
  76. 121 0
      app/Http/Controllers/GiftPackController.php
  77. 68 0
      app/Http/Kernel.php
  78. 21 0
      app/Http/Middleware/Authenticate.php
  79. 17 0
      app/Http/Middleware/EncryptCookies.php
  80. 17 0
      app/Http/Middleware/PreventRequestsDuringMaintenance.php
  81. 32 0
      app/Http/Middleware/RedirectIfAuthenticated.php
  82. 19 0
      app/Http/Middleware/TrimStrings.php
  83. 20 0
      app/Http/Middleware/TrustHosts.php
  84. 28 0
      app/Http/Middleware/TrustProxies.php
  85. 17 0
      app/Http/Middleware/VerifyCsrfToken.php
  86. 53 0
      app/Http/Middleware/checkAuthMiddleware.php
  87. 11 0
      app/Models/Account.php
  88. 19 0
      app/Models/Attire.php
  89. 18 0
      app/Models/BoxRecord.php
  90. 11 0
      app/Models/Config.php
  91. 17 0
      app/Models/CouponRecord.php
  92. 25 0
      app/Models/FittingRoom.php
  93. 17 0
      app/Models/Gift.php
  94. 20 0
      app/Models/GiftBox.php
  95. 21 0
      app/Models/GiftPack.php
  96. 24 0
      app/Models/GiftRecord.php
  97. 14 0
      app/Models/LiveRoom.php
  98. 24 0
      app/Models/PackRecord.php
  99. 23 0
      app/Models/PasterRecord.php
  100. 14 0
      app/Models/Resource.php

+ 18 - 0
.editorconfig

@@ -0,0 +1,18 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.{yml,yaml}]
+indent_size = 2
+
+[docker-compose.yml]
+indent_size = 4

+ 52 - 0
.env.example

@@ -0,0 +1,52 @@
+APP_NAME=Laravel
+APP_ENV=local
+APP_KEY=
+APP_DEBUG=true
+APP_URL=http://localhost
+
+LOG_CHANNEL=stack
+LOG_DEPRECATIONS_CHANNEL=null
+LOG_LEVEL=debug
+
+DB_CONNECTION=mysql
+DB_HOST=127.0.0.1
+DB_PORT=3306
+DB_DATABASE=avatar
+DB_USERNAME=root
+DB_PASSWORD=
+
+BROADCAST_DRIVER=log
+CACHE_DRIVER=file
+FILESYSTEM_DRIVER=local
+QUEUE_CONNECTION=sync
+SESSION_DRIVER=file
+SESSION_LIFETIME=120
+
+MEMCACHED_HOST=127.0.0.1
+
+REDIS_HOST=127.0.0.1
+REDIS_PASSWORD=null
+REDIS_PORT=6379
+
+MAIL_MAILER=smtp
+MAIL_HOST=mailhog
+MAIL_PORT=1025
+MAIL_USERNAME=null
+MAIL_PASSWORD=null
+MAIL_ENCRYPTION=null
+MAIL_FROM_ADDRESS=null
+MAIL_FROM_NAME="${APP_NAME}"
+
+AWS_ACCESS_KEY_ID=
+AWS_SECRET_ACCESS_KEY=
+AWS_DEFAULT_REGION=us-east-1
+AWS_BUCKET=
+AWS_USE_PATH_STYLE_ENDPOINT=false
+
+PUSHER_APP_ID=
+PUSHER_APP_KEY=
+PUSHER_APP_SECRET=
+PUSHER_APP_CLUSTER=mt1
+
+MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
+MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

+ 72 - 0
.env.online

@@ -0,0 +1,72 @@
+APP_NAME=ttr
+APP_ENV=local
+APP_KEY=base64:JcJlh2Yq29YGFK2iQXHSPuU3nPwC+/aCx1i3JNFDJaE=
+APP_DEBUG=true
+APP_URL=https://nebulabeat.com/
+ADMIN_ASSETS_SERVER=https://nebulabeat.com/
+
+LOG_CHANNEL=daily
+LOG_DEPRECATIONS_CHANNEL=null
+LOG_LEVEL=debug
+
+BCLIENTID=5a2ac6f149df41d5
+BSECRET=aad6cba900c64171a1c89a9334fb6f8d
+
+DB_CONNECTION=mysql
+DB_HOST=10.21.33.7
+DB_PORT=3306
+DB_DATABASE=rhythm_backend
+DB_USERNAME=rhythm
+DB_PASSWORD=lGoGOICMOKX50qn0sd5r
+
+BROADCAST_DRIVER=log
+CACHE_DRIVER=file
+FILESYSTEM_DRIVER=local
+QUEUE_CONNECTION=sync
+SESSION_DRIVER=redis
+SESSION_LIFETIME=120
+SESSION_CONNECTION=session
+
+MEMCACHED_HOST=127.0.0.1
+
+REDIS_HOST=10.21.33.3
+REDIS_PASSWORD="@#4jkdf@#$jkDA"
+REDIS_PORT=6379
+REDIS_CACHE_DB=0
+
+MAIL_MAILER=smtp
+MAIL_HOST=mailhog
+MAIL_PORT=1025
+MAIL_USERNAME=null
+MAIL_PASSWORD=null
+MAIL_ENCRYPTION=null
+MAIL_FROM_ADDRESS=null
+MAIL_FROM_NAME="${APP_NAME}"
+
+AWS_ACCESS_KEY_ID=
+AWS_SECRET_ACCESS_KEY=
+AWS_DEFAULT_REGION=us-east-1
+AWS_BUCKET=
+AWS_USE_PATH_STYLE_ENDPOINT=false
+
+PUSHER_APP_ID=
+PUSHER_APP_KEY=
+PUSHER_APP_SECRET=
+PUSHER_APP_CLUSTER=mt1
+
+MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
+MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
+
+COSV5_APP_ID=1252149920
+COSV5_SECRET_ID=AKIDJTSFo8E5h4C5k9LK4artlMhmcCWaQ0LR
+COSV5_SECRET_KEY=tXv31k7F7kANK2VjiRvCF3b095oKabNu
+COSV5_TOKEN=null
+COSV5_TIMEOUT=60
+COSV5_CONNECT_TIMEOUT=60
+COSV5_BUCKET=rhythm-1252149920
+COSV5_REGION=ap-beijing
+COSV5_CDN=http://static.nebulabeat.com
+COSV5_SCHEME=http
+COSV5_READ_FROM_CDN=true
+COSV5_CDN_KEY=
+COSV5_ENCRYPT=false

+ 5 - 0
.gitattributes

@@ -0,0 +1,5 @@
+* text=auto
+*.css linguist-vendored
+*.scss linguist-vendored
+*.js linguist-vendored
+CHANGELOG.md export-ignore

+ 15 - 0
.gitignore

@@ -0,0 +1,15 @@
+/node_modules
+/public/hot
+/public/storage
+/storage/*.key
+/vendor
+.env
+.env.backup
+.phpunit.result.cache
+docker-compose.override.yml
+Homestead.json
+Homestead.yaml
+npm-debug.log
+yarn-error.log
+/.idea
+/.vscode

+ 14 - 0
.styleci.yml

@@ -0,0 +1,14 @@
+php:
+  preset: laravel
+  version: 8
+  disabled:
+    - no_unused_imports
+  finder:
+    not-name:
+      - index.php
+      - server.php
+js:
+  finder:
+    not-name:
+      - webpack.mix.js
+css: true

+ 66 - 0
README.md

@@ -0,0 +1,66 @@
+<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400"></a></p>
+
+<p align="center">
+<a href="https://travis-ci.org/laravel/framework"><img src="https://travis-ci.org/laravel/framework.svg" alt="Build Status"></a>
+<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
+<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
+<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
+</p>
+
+## About Laravel
+
+Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
+
+- [Simple, fast routing engine](https://laravel.com/docs/routing).
+- [Powerful dependency injection container](https://laravel.com/docs/container).
+- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
+- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
+- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
+- [Robust background job processing](https://laravel.com/docs/queues).
+- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
+
+Laravel is accessible, powerful, and provides tools required for large, robust applications.
+
+## Learning Laravel
+
+Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
+
+If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 1500 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
+
+## Laravel Sponsors
+
+We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell).
+
+### Premium Partners
+
+- **[Vehikl](https://vehikl.com/)**
+- **[Tighten Co.](https://tighten.co)**
+- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
+- **[64 Robots](https://64robots.com)**
+- **[Cubet Techno Labs](https://cubettech.com)**
+- **[Cyber-Duck](https://cyber-duck.co.uk)**
+- **[Many](https://www.many.co.uk)**
+- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)**
+- **[DevSquad](https://devsquad.com)**
+- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
+- **[OP.GG](https://op.gg)**
+- **[CMS Max](https://www.cmsmax.com/)**
+- **[WebReinvent](https://webreinvent.com/?utm_source=laravel&utm_medium=github&utm_campaign=patreon-sponsors)**
+- **[Lendio](https://lendio.com)**
+- **[Romega Software](https://romegasoftware.com)**
+
+## Contributing
+
+Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
+
+## Code of Conduct
+
+In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
+
+## Security Vulnerabilities
+
+If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
+
+## License
+
+The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).

+ 25 - 0
app/Admin/Actions/Grid/CouponSetAction.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Admin\Actions\Grid;
+
+use Dcat\Admin\Actions\Response;
+use Dcat\Admin\Grid\Tools\AbstractTool;
+use Dcat\Admin\Traits\HasPermissions;
+use Illuminate\Contracts\Auth\Authenticatable;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Http\Request;
+
+class CouponSetAction extends AbstractTool
+{
+    /**
+     * @return string
+     */
+    public function render()
+    {
+        return \Dcat\Admin\Widgets\Modal::make()
+            ->xl()
+            ->title('限时活动介绍')
+            ->body(\App\Admin\Forms\CouponSet::make()) // 传递自定义参数
+            ->button('<a class="btn btn-primary grid-refresh btn-mini btn-outline" href="javascript:void(0)">限时活动介绍</a>');
+    }
+}

+ 29 - 0
app/Admin/Actions/Grid/GiftBoxHitAction.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Admin\Actions\Grid;
+
+use Dcat\Admin\Actions\Response;
+use Dcat\Admin\Grid\Tools\AbstractTool;
+use Dcat\Admin\Traits\HasPermissions;
+use Illuminate\Contracts\Auth\Authenticatable;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Http\Request;
+
+class GiftBoxHitAction extends AbstractTool
+{
+    /**
+     * Handle the action request.
+     *
+     * @param Request $request
+     *
+     * @return Response
+     */
+    public function render()
+    {
+        return \Dcat\Admin\Widgets\Modal::make()
+            ->lg()
+            ->title('保底设置')
+            ->body(\App\Admin\Forms\GiftBoxHit::make()) // 传递自定义参数
+            ->button('<a class="btn btn-primary grid-refresh btn-mini btn-outline" href="javascript:void(0)">保底设置</a>');
+    }
+}

+ 27 - 0
app/Admin/Actions/Grid/LevelPasterAction.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Admin\Actions\Grid;
+
+use Dcat\Admin\Actions\Response;
+use Dcat\Admin\Grid\Tools\AbstractTool;
+use Illuminate\Http\Request;
+
+class LevelPasterAction extends AbstractTool
+{
+
+    /**
+     * Handle the action request.
+     *
+     * @param Request $request
+     *
+     * @return Response
+     */
+    public function render()
+    {
+        return \Dcat\Admin\Widgets\Modal::make()
+            ->lg()
+            ->title('回收贴纸数')
+            ->body(\App\Admin\Forms\LevelPaster::make()) // 传递自定义参数
+            ->button('<a class="btn btn-primary grid-refresh btn-mini btn-outline" href="javascript:void(0)">回收设置</a>');
+    }
+}

+ 26 - 0
app/Admin/Actions/Grid/LevelPercentAction.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace App\Admin\Actions\Grid;
+
+use Dcat\Admin\Actions\Response;
+use Dcat\Admin\Grid\Tools\AbstractTool;
+
+class LevelPercentAction extends AbstractTool
+{
+
+    /**
+     * Handle the action request.
+     *
+     * @param Request $request
+     *
+     * @return Response
+     */
+    public function render()
+    {
+        return \Dcat\Admin\Widgets\Modal::make()
+            ->lg()
+            ->title('修改概率')
+            ->body(\App\Admin\Forms\LevelPercent::make()) // 传递自定义参数
+            ->button('<a class="btn btn-primary grid-refresh btn-mini btn-outline" href="javascript:void(0)">概率设置</a>');
+    }
+}

+ 29 - 0
app/Admin/Actions/Grid/NewUserCouponAction.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Admin\Actions\Grid;
+
+use Dcat\Admin\Actions\Response;
+use Dcat\Admin\Grid\Tools\AbstractTool;
+use Dcat\Admin\Traits\HasPermissions;
+use Illuminate\Contracts\Auth\Authenticatable;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Http\Request;
+
+class NewUserCouponAction extends AbstractTool
+{
+    /**
+     * Handle the action request.
+     *
+     * @param Request $request
+     *
+     * @return Response
+     */
+    public function render()
+    {
+        return \Dcat\Admin\Widgets\Modal::make()
+            ->lg()
+            ->title('新人礼包')
+            ->body(\App\Admin\Forms\NewUserCoupon::make()) // 传递自定义参数
+            ->button('<a class="btn btn-primary grid-refresh btn-mini btn-outline" href="javascript:void(0)">新人礼包</a>');
+    }
+}

+ 25 - 0
app/Admin/Actions/Grid/PackRecordAction.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Admin\Actions\Grid;
+
+use Dcat\Admin\Actions\Response;
+use Dcat\Admin\Grid\Tools\AbstractTool;
+use Dcat\Admin\Traits\HasPermissions;
+use Illuminate\Contracts\Auth\Authenticatable;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Http\Request;
+
+class PackRecordAction extends AbstractTool
+{
+    /**
+     * @return string
+     */
+    public function render()
+    {
+        return \Dcat\Admin\Widgets\Modal::make()
+            ->xl()
+            ->title('兑换记录')
+            ->body(\App\Admin\Renderable\PackRecordTable::make()) // 传递自定义参数
+            ->button('<a class="btn btn-primary grid-refresh btn-mini btn-outline" href="javascript:void(0)">兑换记录</a>');
+    }
+}

+ 92 - 0
app/Admin/Controllers/AccountController.php

@@ -0,0 +1,92 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\Account;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class AccountController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new Account(), function (Grid $grid) {
+            $grid->column('id')->sortable();
+            $grid->column('avatar','用户头像')->image(config("filesystems.disks.cosv5.url"), 60, 60);;
+            $grid->column('username');
+            $grid->column('coupon')->display(function($v) {
+                return $v.' <a href="/admin/coupon_records?account_id='.$this->id.'" target="_blank">查看明细</a>';
+            });
+            $grid->column('box_record','开盒记录')->display(function($v) {
+                return '<a href="/admin/box_records?account_id='.$this->id.'" target="_blank">点击查看</a>';
+            });
+            $grid->column('paster');
+            $grid->column('uid','uid')->help("B站用户ID");
+            $grid->column('created_at');
+            $grid->column('updated_at')->sortable();
+
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->panel();
+                $filter->expand();
+                $filter->equal('uid','用户UID')->width(2);
+                $filter->like('name','用户名称')->width(2);
+            });
+            $grid->disableCreateButton();
+            $grid->enableDialogCreate();
+            $grid->setDialogFormDimensions('40%', '50%');
+            $grid->withBorder();
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                $actions->quickEdit(true);
+                $actions->disableEdit();
+                $actions->disableView();
+            });
+            $grid->tools(function (Grid\Tools $tools) {
+                $tools->append(new \App\Admin\Actions\Grid\NewUserCouponAction());
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new Account(), function (Show $show) {
+            $show->field('id');
+            $show->field('username');
+            $show->field('coupon');
+            $show->field('paster');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new Account(), function (Form $form) {
+            // $form->display('id');
+            $form->text('username');
+            $form->number('coupon');
+            $form->number('paster');
+            //
+            // $form->display('created_at');
+            // $form->display('updated_at');
+        });
+    }
+}

+ 170 - 0
app/Admin/Controllers/AttireController.php

@@ -0,0 +1,170 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\Attire;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class AttireController extends AdminController
+{
+    public $cates = [
+        '套装' => '套装',
+        '皮肤' => '皮肤',
+    ];
+    public $levels = [
+        'N' => 'N',
+        'R' => 'R',
+        'SR' => 'SR',
+        'SSR' => 'SSR',
+    ];
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new Attire(), function (Grid $grid) {
+            $grid->column('id')->sortable();
+            $grid->column('name');
+            $grid->column('cate');
+            $grid->column('level');
+            $grid->column('img_1')->image(config("filesystems.disks.cosv5.url"), 100, 100);
+            $grid->column('img_2')->image(config("filesystems.disks.cosv5.url"), 100, 100);
+            $grid->column('is_default')->using(['','默认'])->label();
+            // $grid->column('created_at');
+            // $grid->column('updated_at')->sortable();
+
+            $grid->enableDialogCreate();
+            $grid->setDialogFormDimensions('50%', '60%');
+            $grid->withBorder();
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                $actions->quickEdit(true);
+                $actions->disableEdit();
+                $actions->disableView();
+            });
+            $grid->model()->orderByDesc("id");
+            //
+            $grid->filter(function ($filter) {
+                // 展开过滤器
+                $filter->panel();
+                $filter->expand();
+                $filter->withoutInputBorder();
+                // 在这里添加字段过滤器
+                $filter->equal('id')->width(2);
+                $filter->like('name')->width(3);
+                $filter->equal('cate')->select($this->cates)->width(2);
+                $filter->equal('level')->select($this->levels)->width(2);
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new Attire(), function (Show $show) {
+            $show->field('id');
+            $show->field('name');
+            $show->field('cate');
+            $show->field('img_1');
+            $show->field('img_2');
+            $show->field('retrieve_pasters');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new Attire(['giftBox']), function (Form $form) {
+            // $form->display('id');
+            $form->text('name')->required();
+            $form->radio('cate')->options($this->cates)->required()->default(1);
+            $form->select('level')->options($this->levels);
+            $form->image('img_1')->autoUpload()->removable(false)->required();
+            $form->image('img_2')->autoUpload()->removable(false)->required();
+            // $form->number('retrieve_pasters');
+           
+            // $form->display('created_at');
+            // $form->display('updated_at');
+            //
+            // $form->saving(function (Form $form) {
+            //     // 判断是否是新增操作
+            //     if ($form->isCreating()) {
+            //         //
+            //         $obj = new \App\Models\Attire();
+            //         $obj->name = $form->input("name");
+            //         $obj->cate = $form->input("cate");
+            //         $obj->img_1 = $form->input("img_1");
+            //         $obj->img_2 = $form->input("img_2");
+            //         $obj->save();
+            //         //
+            //         if ($form->input("giftBox.level")) {
+            //             $obj2 = new \App\Models\GiftBox();
+            //             $obj2->attire_id = $obj->id;
+            //             $obj2->level = $form->input("giftBox.level");
+            //             $obj2->save();
+            //         }
+            //         //
+            //         return $form->response()->success('创建成功');
+            //     } else {
+            //         $obj = $form->model();
+            //         $obj->name = $form->input("name");
+            //         $obj->cate = $form->input("cate");
+            //         $obj->img_1 = $form->input("img_1");
+            //         $obj->img_2 = $form->input("img_2");
+            //         $obj->save();
+            //         //
+            //         $obj2 = \App\Models\GiftBox::where("attire_id", $obj->id)->first();
+            //         if ($form->input("giftBox.level")) {
+            //             if (!$obj2) {
+            //                 $obj2 = new \App\Models\GiftBox();
+            //                 $obj2->attire_id = $obj->id;
+            //                 $obj2->level = $form->input("giftBox.level");
+            //                 $obj2->save();
+            //             } else {
+            //                 $obj2->level = $form->input("giftBox.level");
+            //                 $obj2->save();
+            //             }
+            //         } else {
+            //             if ($obj2) {
+            //                 $obj2->delete();
+            //             }
+            //         }
+            //         //
+            //         return $form->response()->success('更新成功');
+            //     }
+            // });
+            //
+            // $form->deleted(function (Form $form, $result) {
+            //     // 获取待删除行数据,这里获取的是一个二维数组
+            //     $data = $form->model()->toArray();
+            //     // 通过 $result 可以判断数据是否删除成功
+            //     if (!$result) {
+            //         return $form->response()->error('数据删除失败');
+            //     }
+            //     foreach ($data as $k => $v) {
+            //         if (isset($v['gift_box']['id']) && $v['gift_box']['id']) {
+            //             \App\Models\GiftBox::Find($v['gift_box']['id'])->delete();
+            //         }
+            //     }
+            //     // 返回删除成功提醒,此处跳转参数无效
+            //     return $form->response()->success('删除成功');
+            // });
+        });
+    }
+}

+ 9 - 0
app/Admin/Controllers/AuthController.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use Dcat\Admin\Http\Controllers\AuthController as BaseAuthController;
+
+class AuthController extends BaseAuthController
+{
+}

+ 162 - 0
app/Admin/Controllers/BoxRecordController.php

@@ -0,0 +1,162 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\BoxRecord;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class BoxRecordController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new BoxRecord(['account']), function (Grid $grid) {
+            $grid->column('id')->sortable();
+            $grid->column('account.uid','用户UID');
+            $grid->column('account.avatar','用户头像')->image(config("filesystems.disks.cosv5.url"), 60, 60);
+            $grid->column('account.username','用户名称')->display(function($v) {
+                return "<a href='/admin/accounts?id={$this->account_id}' target='_blank'>{$v}</a>";
+            });
+            $grid->column('num');
+            $grid->column('box_ids')->display(function($v) {
+                return "点击查看(".($v? count(explode(",", $v)): 0).")";
+            })->expand(function () {
+                if($this->box_ids) {
+                    return \App\Admin\Renderable\BoxRecordAttiresTable::make(["ids"=>$this->box_ids]);
+                }
+                return "";
+            });
+            // $grid->column('attire_ids');
+            $grid->column('retrieve_pasters');
+            // $grid->column('retrieve_attire_ids');
+            $grid->column('retrieve_box_ids')->display(function($v) {
+                return "点击查看(".($v? count(explode(",", $v)):0).")";
+            })->expand(function () {
+                if($this->retrieve_box_ids) {
+                    return \App\Admin\Renderable\BoxRecordRetrieveAttiresTable::make(["ids"=>$this->retrieve_box_ids]);
+                }
+                return "";
+            });
+            $grid->column('cost_coupons');
+            $grid->column('created_at');
+            // $grid->column('updated_at')->sortable();
+        
+            $grid->model()->orderByDesc("id");
+            $grid->disableActions();
+            $grid->disableBatchDelete();
+            $grid->disableRefreshButton();
+            $grid->disableCreateButton();
+            $grid->disableRowSelector();
+            // $grid->simplePaginate();
+            $grid->paginate(15);
+            $grid->addTableClass(['table-text-center']);
+            // $grid->disableToolbar();
+            $grid->filter(function ($filter) {
+                // 展开过滤器
+                $filter->panel();
+$filter->expand();
+                $filter->where('aid', function ($query) {
+                    $query->whereHas('account', function ($query) {
+                        $query->where('uid', $this->input);
+                    });
+                }, '用户UID')->width(2);
+                // $filter->equal('attire.cate', '类别')->select($this->cates)->width(2); // 设置编辑数据显示
+                $filter->equal('account_id','用户名')->select(\App\Models\Account::pluck('username','id'))->width(2);
+            });
+            //
+            $grid->export()->rows(function ($rows) {
+                // dump($rows);
+                foreach ($rows as &$row) {
+                    $tmp = $row->toArray();
+                    // dd($tmp);
+                    //
+                    $boxIds = explode(",", $tmp['box_ids']);
+                    if(count($boxIds)>0) {
+                        $tmp3 = \App\Models\GiftBox::withTrashed()
+                        ->whereIn('id', $boxIds)
+                        ->with(['attire'])
+                        ->get()
+                        ->toArray();
+                    }
+                    //
+                    $boxNames = [];
+                    foreach($tmp3 as $v) {
+                        $boxNames[] = $v['attire']['name'];
+                    }
+                    //
+                    $tmp['retrieve_box_ids'] = $tmp['retrieve_box_ids'] ?? "";
+                    $retrieveBoxIds = explode(",", $tmp['retrieve_box_ids']);
+                    if(count($retrieveBoxIds)>0) {
+                        $tmp2 = \App\Models\GiftBox::withTrashed()
+                        ->whereIn('id', $retrieveBoxIds)
+                        ->with(['attire'])
+                        ->get()
+                        ->toArray();
+                    }
+                    $retrieveNames = [];
+                    foreach($tmp2 as $v) {
+                        $retrieveNames[] = $v['attire']['name'];
+                    }
+                    //
+                    $tmp = array_column($tmp, null, 'id');
+                    //
+                    $row['account.username'] = $tmp['account']['username']?? '';
+                    $row['box_ids'] = implode("\r\n", $boxNames);
+                    $row['retrieve_box_ids'] = implode("\r\n", $retrieveNames);
+                }
+                //
+                return $rows;
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new BoxRecord(), function (Show $show) {
+            $show->field('id');
+            $show->field('account_id');
+            $show->field('num');
+            $show->field('attire_ids');
+            $show->field('retrieve_pasters');
+            $show->field('retrieve_attire_ids');
+            $show->field('cost_coupons');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new BoxRecord(), function (Form $form) {
+            $form->display('id');
+            $form->text('account_id');
+            $form->text('num');
+            $form->text('attire_ids');
+            $form->text('retrieve_pasters');
+            $form->text('retrieve_attire_ids');
+            $form->text('cost_coupons');
+        
+            $form->display('created_at');
+            $form->display('updated_at');
+        });
+    }
+}

+ 110 - 0
app/Admin/Controllers/ConfigController.php

@@ -0,0 +1,110 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\Config;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Support\JavaScript;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class ConfigController extends AdminController
+{
+
+    // public $types=['文本框','数值','编辑器'];
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new Config(), function (Grid $grid) {
+            // $grid->column('id')->sortable();
+            $grid->column('name')->width("150px");
+            $grid->column('key');
+            $grid->column('val')->display(function() {
+                return $this->type==1? $this->val1: $this->val; 
+            });
+            $grid->column('beizhu');
+            // $grid->column('created_at');
+            $grid->column('updated_at')->sortable();
+            $grid->model()->whereNotIn("key",['box_level_percent','box_level_paster','coupon_configs']);
+            // $grid->filter(function (Grid\Filter $filter) {
+            //     $filter->equal('id');
+            // });
+            $grid->model()->orderBy("id","desc");
+
+            // $grid->enableDialogCreate();
+            // $grid->setDialogFormDimensions('70%', '60%');
+            $grid->withBorder();
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                // $actions->quickEdit(true);
+                // $actions->disableEdit();
+                $actions->disableView();
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new Config(), function (Show $show) {
+            $show->field('id');
+            $show->field('key');
+            $show->field('val');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new Config(), function (Form $form) {
+            // $form->display('id');
+            $form->text('name');
+            if ($form->isCreating()) {
+                $form->text('key')->required();
+            } else {
+                $form->text('key')->readonly();
+            }
+            $form->radio('type')
+                ->when(0, function (Form $form) {
+                    $form->text('val','内容');
+                })
+                ->when(1, function (Form $form) {
+                    $form->editor('val1','内容')->options([
+                        'toolbar' => [],
+                        'setup' => JavaScript::make(
+                            <<<JS
+                    function (editor) {
+                        console.log('编辑器初始化成功', editor)
+                    }
+                    JS
+                        ),
+                    ]);
+                })
+                ->options([
+                    0 => '显示文本框',
+                    1 => '显示编辑器',
+                ])->default(0);
+            //
+            $form->textarea('beizhu');
+
+            // $form->display('created_at');
+            // $form->display('updated_at');
+        });
+    }
+}

+ 133 - 0
app/Admin/Controllers/CouponRecordController.php

@@ -0,0 +1,133 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\CouponRecord;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class CouponRecordController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new CouponRecord(['account']), function (Grid $grid) {
+            $grid->column('id')->sortable();
+            $grid->column('account.uid','用户UID');
+            $grid->column('account.avatar','用户头像')->image(config("filesystems.disks.cosv5.url"), 60, 60);
+            $grid->column('account.username','用户名称')->display(function($v) {
+                return "<a href='/admin/accounts?id={$this->account_id}' target='_blank'>{$v}</a>";
+            });
+            $grid->column('add_cnt');
+            $grid->column('type')->using(['','消耗','弹幕增加','打赏增加','兑换礼品增加','兑换礼包增加','新人礼包'])->label();
+
+            $grid->column('record','记录明细')->display(function($v) {
+                if($this->type == 1) {
+                    return '开盒记录';
+                } elseif($this->type == 4) {
+                    return '兑换记录';
+                }
+            })->modal(function ($modal) {
+                if($this->type == 1) {
+                    $modal->title('开礼盒记录');
+                    // 允许在闭包内返回异步加载类的实例
+                    if($this->box_record_id) {
+                        return \App\Admin\Renderable\BoxRecordTable::make(['id' => $this->box_record_id]);
+                    }
+                    return false; 
+                } elseif($this->type == 4) {
+                    $modal->title('礼品兑换记录');
+                    // 允许在闭包内返回异步加载类的实例
+                    if($this->gift_record_id) {
+                        return \App\Admin\Renderable\GiftRecordTable::make(['id' => $this->gift_record_id]);
+                    }
+                    return false; 
+                }
+            });
+            // $grid->column('gift_record_id')->display('查看')->modal(function ($modal) {
+            //     $modal->title('兑换记录');
+            //     // 允许在闭包内返回异步加载类的实例
+            //     if($this->gift_record_id) {
+            //         return \App\Admin\Renderable\GiftRecordTable::make(['id' => $this->gift_record_id]);
+            //     }
+            //     return false; 
+            // });
+            $grid->column('pack_record_id');
+            $grid->column('day');
+            $grid->column('created_at');
+            // $grid->column('updated_at')->sortable();
+
+            $grid->model()->orderByDesc("id");
+            $grid->disableActions();
+            $grid->disableBatchDelete();
+            $grid->disableRefreshButton();
+            $grid->disableCreateButton();
+            $grid->disableRowSelector();
+            // $grid->simplePaginate();
+            $grid->paginate(15);
+            $grid->addTableClass(['table-text-center']);
+            // $grid->disableToolbar();
+            $grid->filter(function ($filter) {
+                // 展开过滤器
+                $filter->panel();
+$filter->expand();
+                // $filter->equal('attire.cate', '类别')->select($this->cates)->width(2); // 设置编辑数据显示
+                $filter->equal('account_id','用户名')->select(\App\Models\Account::pluck('username','id'))->width(3);
+                $filter->equal('type')->select([1=>'消耗',2=>'弹幕增加',3=>'打赏增加',4=>'兑换礼品增加',5=>'兑换礼包增加',6=>'新人礼包'])->width(3); // 设置编辑数据显示
+            });
+            //
+            $grid->tools(function (Grid\Tools $tools) {
+                $tools->append(new \App\Admin\Actions\Grid\CouponSetAction());
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new CouponRecord(), function (Show $show) {
+            $show->field('id');
+            $show->field('account_id');
+            $show->field('add_cnt');
+            $show->field('type');
+            $show->field('gift_box_id');
+            $show->field('gift_pack_id');
+            $show->field('day');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new CouponRecord(), function (Form $form) {
+            $form->display('id');
+            $form->text('account_id');
+            $form->text('add_cnt');
+            $form->text('type');
+            $form->text('gift_box_id');
+            $form->text('gift_pack_id');
+            $form->text('day');
+
+            $form->display('created_at');
+            $form->display('updated_at');
+        });
+    }
+}

+ 117 - 0
app/Admin/Controllers/FittingRoomController.php

@@ -0,0 +1,117 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\FittingRoom;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+use App\Admin\Renderable\AttireTable; // 筛选表格弹框
+
+class FittingRoomController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new FittingRoom(['account','attire']), function (Grid $grid) {
+            $grid->column('id')->sortable();
+            $grid->column('account.uid','用户UID');
+            $grid->column('account.username','用户名称')->display(function($v) {
+                return "<a href='/admin/accounts?id={$this->account_id}' target='_blank'>{$v}</a>";
+            });
+            $grid->column('attire.name', '装扮名称');
+            $grid->column('attire.img_1', '正面图片')->image(config("filesystems.disks.cosv5.url"), 100, 100);
+            $grid->column('attire.img_2', '背面图片')->image(config("filesystems.disks.cosv5.url"), 100, 100);
+            $grid->column('attire.cate', '类别');
+            $grid->column('curr_save')->using(['否','是'])->label();
+            $grid->column('curr_upload')->using(['否','是'])->label();
+            $grid->column('created_at');
+            $grid->column('updated_at');
+            //
+            $grid->enableDialogCreate();
+            $grid->setDialogFormDimensions('40%', '50%');
+            $grid->withBorder();
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                $actions->quickEdit(true);
+                $actions->disableEdit();
+                $actions->disableView();
+            });
+            $grid->model()->orderByDesc("id");
+            //
+            $grid->filter(function ($filter) {
+                // 展开过滤器
+                $filter->panel();
+$filter->expand();
+                $filter->withoutInputBorder();
+                // 在这里添加字段过滤器
+                // $filter->equal('id')->width(2);
+                $filter->where('aid', function ($query) {
+                    $query->whereHas('account', function ($query) {
+                        $query->where('uid', $this->input);
+                    });
+                }, '用户UID')->width(2);
+                $filter->equal('account_id','用户名称')->select(\App\Models\Account::pluck('username','id'))->width(2);
+                $filter->equal('attire_id', '装扮')
+                    ->selectTable(AttireTable::make()) // 设置渲染类实例,并传递自定义参数
+                    ->title('装扮列表')
+                    ->dialogWidth('50%') // 弹窗宽度,默认 800px
+                    ->model(\App\Models\Attire::class, 'id', 'name')->width(2); // 设置编辑数据显示
+                // $filter->equal('attire.cate', '类别')->select($this->cates)->width(2); // 设置编辑数据显示
+                
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new FittingRoom(), function (Show $show) {
+            $show->field('id');
+            $show->field('account_id');
+            $show->field('name');
+            $show->field('cate');
+            $show->field('img_1');
+            $show->field('img_2');
+            $show->field('curr_save');
+            $show->field('curr_upload');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new FittingRoom(), function (Form $form) {
+            // $form->display('id');
+            $form->select('account_id')->options(\App\Models\Account::pluck('username','id'));
+            $form->selectTable('attire_id', '装扮') // 设置渲染类实例,并传递自定义参数
+                ->title('装扮列表')
+                ->dialogWidth('50%') // 弹窗宽度,默认 800px
+                ->from(AttireTable::make())
+                ->model(\App\Models\Attire::class, 'id', 'name')
+                // ->rules('unique:fitting_rooms,attire_id,$selfId,id', ['unique' => '已经在礼盒中了,请选择其它的'])
+                ->required();
+            $form->switch('curr_save');
+            $form->switch('curr_upload');
+
+            // $form->display('created_at');
+            // $form->display('updated_at');
+        });
+    }
+}

+ 118 - 0
app/Admin/Controllers/GiftBoxController.php

@@ -0,0 +1,118 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\GiftBox;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+use App\Admin\Renderable\AttireTable; // 筛选表格弹框
+
+class GiftBoxController extends AdminController
+{
+    public $levels = [
+        'N' => 'N',
+        'R' => 'R',
+        'SR' => 'SR',
+        'SSR' => 'SSR',
+    ];
+    public $cates = [
+        '套装' => '套装',
+        '皮肤' => '皮肤',
+    ];
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new GiftBox(['attire']), function (Grid $grid) {
+            $grid->column('id');
+            $grid->column('attire.name', '装扮名称');
+            $grid->column('attire.img_1', '正面图片')->image(config("filesystems.disks.cosv5.url"), 100, 100);
+            $grid->column('attire.img_2', '背面图片')->image(config("filesystems.disks.cosv5.url"), 100, 100);
+            $grid->column('attire.cate', '类别');
+            $grid->column('attire.level','等级');
+            $grid->column('sort')->editable(true)->sortable();
+            // $grid->column('created_at');
+            // $grid->column('updated_at');
+
+            $grid->enableDialogCreate();
+            $grid->setDialogFormDimensions('40%', '30%');
+            $grid->withBorder();
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                $actions->quickEdit(false);
+                $actions->disableEdit();
+                $actions->disableView();
+            });
+            $grid->model()->orderBy("sort","asc")->orderBy("id","asc");
+            //
+            $grid->filter(function ($filter) {
+                // 展开过滤器
+                $filter->panel();
+$filter->expand();
+                $filter->withoutInputBorder();
+                // 在这里添加字段过滤器
+                // $filter->equal('id')->width(2);
+                $filter->equal('attire_id', '装扮')
+                    ->selectTable(AttireTable::make()) // 设置渲染类实例,并传递自定义参数
+                    ->title('装扮列表')
+                    ->dialogWidth('50%') // 弹窗宽度,默认 800px
+                    ->model(\App\Models\Attire::class, 'id', 'name')->width(3); // 设置编辑数据显示
+                $filter->equal('attire.cate', '类别')->select($this->cates)->width(2); // 设置编辑数据显示
+                $filter->equal('attire.level','等级')->select($this->levels)->width(2);
+            });
+            //
+            $grid->tools(function (Grid\Tools $tools) {
+                $tools->append(new \App\Admin\Actions\Grid\LevelPercentAction());
+                $tools->append(new \App\Admin\Actions\Grid\LevelPasterAction());
+                $tools->append(new \App\Admin\Actions\Grid\GiftBoxHitAction());
+                $tools->append('<a target="_blank" class="btn btn-primary grid-refresh btn-mini btn-outline" href="/admin/box_records">开盒记录</a>');
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new GiftBox(), function (Show $show) {
+            $show->field('id');
+            $show->field('attire_id');
+            $show->field('level');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new GiftBox(), function (Form $form) {
+            // $form->display('id');
+            $form->selectTable('attire_id', '装扮') // 设置渲染类实例,并传递自定义参数
+                ->title('装扮列表')
+                ->dialogWidth('50%') // 弹窗宽度,默认 800px
+                ->from(AttireTable::make())
+                ->model(\App\Models\Attire::class, 'id', 'name')
+                ->rules('unique:gift_boxes,attire_id,$selfId,id,deleted_at,NULL', ['unique' => '已经在礼盒中了,请选择其它的'])
+                ->required();
+            $form->number("sort");
+            // $form->radio('level')->options($this->levels)->default('N')->required();
+
+            // $form->display('created_at');
+            // $form->display('updated_at');
+        });
+    }
+}

+ 129 - 0
app/Admin/Controllers/GiftController.php

@@ -0,0 +1,129 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\Gift;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+use App\Admin\Renderable\AttireTable; // 筛选表格弹框
+
+class GiftController extends AdminController
+{
+
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new Gift(['attire']), function (Grid $grid) {
+            //
+            $types = ['','礼劵','装扮'];
+            //
+            $grid->column('id');
+            // $grid->column('name');
+            $grid->column('type')->using($types)->label();
+            // $grid->column('attire_id');
+            $grid->column('attire.name', '装扮名称');
+            $grid->column('attire.img_1', '图片')->display(function($v) {
+                if($this->type == 1) {
+                    return "<img src='".\Storage::disk('cosv5')->url($this->img)."' style='height:100px;width:auto;' />";
+                } else {
+                    return "<img src='".\Storage::disk('cosv5')->url($v)."' style='height:100px;width:auto;' />";
+                }
+            });
+            $grid->column('info')->width("250px");
+            $grid->column('attire.cate', '装扮类别');
+            $grid->column('cost_pasters');
+            $grid->column('limit')->help("限购规则:礼劵是按每月(自然月)限购,装扮是永久");
+            $grid->column('sort')->editable(true);
+            // $grid->column('created_at');
+            // $grid->column('updated_at');
+        
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->equal('id');
+            });
+            $grid->model()->orderBy("sort");
+
+            $grid->enableDialogCreate();
+            $grid->setDialogFormDimensions('50%', '60%');
+            $grid->withBorder();
+            $grid->addTableClass(['table-text-center']);
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                $actions->quickEdit(true);
+                $actions->disableEdit();
+                $actions->disableView();
+            });
+
+            $grid->tools(function (Grid\Tools $tools) {
+                $tools->append('<a target="_blank" class="btn btn-primary grid-refresh btn-mini btn-outline" href="/admin/gift_records">兑换记录</a>');
+            });
+
+            //
+            $grid->export()->rows(function ($rows) use ($types) {
+                // dump($rows);
+                foreach ($rows as &$row) {
+                    unset($row['attire.img_1']);
+                    $tmp = $row->toArray();
+                    $row['type'] = $types[$row['type']];
+                    // dd($tmp);
+                    $row['attire.name'] = $tmp['attire']? $tmp['attire']['name']:'-';
+                    $row['attire.cate'] = $tmp['attire']? $tmp['attire']['cate']:'-';
+                }
+                //
+                return $rows;
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new Gift(), function (Show $show) {
+            $show->field('id');
+            $show->field('type');
+            $show->field('attire_id');
+            $show->field('limit');
+            $show->field('sort');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new Gift(), function (Form $form) {
+            $form->radio('type')
+                ->when(1, function (Form $form) {
+                    $form->image('img','礼劵图片')->autoUpload();
+                })->when(2, function (Form $form) {
+                    $form->selectTable('attire_id', '装扮') // 设置渲染类实例,并传递自定义参数
+                        ->title('装扮列表')
+                        ->dialogWidth('50%') // 弹窗宽度,默认 800px
+                        ->from(AttireTable::make())
+                        ->model(\App\Models\Attire::class, 'id', 'name')
+                        ->default(0);
+                })->options([1=>'礼劵',2=>'装扮'])
+                ->required()
+                ->default(2);
+            $form->textarea("info")->help("建议字数控制在40字左右,超出会省略...")->required();
+            $form->number('cost_pasters')->default(0)->required()->help("限购规则:礼劵是每月限购,装扮是永久");
+            $form->number('limit')->default(1)->required();
+            $form->number('sort')->help("数字大的优先展示");
+        });
+    }
+}

+ 113 - 0
app/Admin/Controllers/GiftPackController.php

@@ -0,0 +1,113 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\GiftPack;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+use App\Admin\Renderable\AttireTable; // 筛选表格弹框
+
+class GiftPackController extends AdminController
+{
+    public $rooms = [];
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        $this->rooms = \App\Models\LiveRoom::pluck("short_name","room_id")->toArray();
+        return Grid::make(new GiftPack(['attire']), function (Grid $grid) {
+            $grid->column('id');
+            $grid->column('name');
+            $grid->column('room_id')->using($this->rooms);
+            $grid->column('coupon');
+            $grid->column('attire.name', '应援装扮');
+            $grid->column('img')->image(config("filesystems.disks.cosv5.url"), 100, 100);
+            // $grid->column('exchage_info');
+            // $grid->column('attire_id');
+            $grid->column('sort');
+            $grid->column('created_at');
+            // $grid->column('updated_at')->sortable();
+
+            $grid->enableDialogCreate();
+            $grid->setDialogFormDimensions('50%', '70%');
+            $grid->withBorder();
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                $actions->quickEdit(true);
+                $actions->disableEdit();
+                $actions->disableView();
+            });
+
+            $grid->model()->orderBy("sort","asc");
+            //
+            $grid->filter(function ($filter) {
+                // 展开过滤器
+                $filter->panel();
+$filter->expand();
+                $filter->withoutInputBorder();
+                // 在这里添加字段过滤器
+                $filter->equal('id')->width(2);
+                $filter->equal('attire_id', '装扮')
+                    ->selectTable(AttireTable::make()) // 设置渲染类实例,并传递自定义参数
+                    ->title('装扮列表')
+                    ->dialogWidth('50%') // 弹窗宽度,默认 800px
+                    ->model(\App\Models\Attire::class, 'id', 'name')->width(3); // 设置编辑数据显示
+                    $filter->equal('room_id')->select($this->rooms)->width(2);
+            });
+            $grid->tools(function (Grid\Tools $tools) {
+                $tools->append(new \App\Admin\Actions\Grid\PackRecordAction());
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new GiftPack(), function (Show $show) {
+            $show->field('id');
+            $show->field('name');
+            $show->field('coupon_cnt');
+            $show->field('attire_ids');
+            $show->field('attire_cnt');
+            $show->field('sort');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        $this->rooms = \App\Models\LiveRoom::pluck("short_name","room_id")->toArray();
+        return Form::make(new GiftPack(), function (Form $form) {
+            // $form->display('id');
+            $form->text('name')->required();
+            $form->select('room_id')->options($this->rooms)->required();
+            $form->selectTable('attire_id', '应援装扮') // 设置渲染类实例,并传递自定义参数
+                ->title('装扮列表')
+                ->dialogWidth('50%') // 弹窗宽度,默认 800px
+                ->from(AttireTable::make())
+                ->model(\App\Models\Attire::class, 'id', 'name')->default(0);
+                //->rules('unique:gift_packs,attire_id,$selfId,id,deleted_at,NULL', ['unique' => '已经在礼包中了,请选择其它的'])
+            $form->number('coupon')->required();
+            $form->image('img')->autoUpload()->removable(false);
+            // $form->textarea('exchage_info')->required();
+            //
+            $form->number('sort');
+        });
+    }
+}

+ 111 - 0
app/Admin/Controllers/GiftRecordController.php

@@ -0,0 +1,111 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\GiftRecord;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+use App\Admin\Renderable\GiftTable; // 筛选表格弹框
+
+class GiftRecordController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new GiftRecord(['account','gift.attire']), function (Grid $grid) {
+            $grid->column('id');
+            $grid->column('account.uid','用户UID');
+            $grid->column('account.avatar','用户头像')->image(config("filesystems.disks.cosv5.url"), 60, 60);
+            $grid->column('account.username','用户名称')->display(function($v) {
+                return "<a href='/admin/accounts?id={$this->account_id}' target='_blank'>{$v}</a>";
+            });
+            $grid->column('gift.type','礼品类型')->using(['','礼劵','装扮'])->label();
+            // $grid->column('attire_id');
+            $grid->column('gift.attire.name', '装扮名称');
+            $grid->column('gift.attire.img_1', '礼品图片')->display(function($v) {
+                if($this->gift->type == 1) {
+                    return "<img src='".\Storage::disk('cosv5')->url($this->gift->img)."' style='height:60px;width:auto;' />";
+                } else {
+                    return "<img src='".\Storage::disk('cosv5')->url($v)."' style='height:60px;width:auto;' />";
+                }
+            });
+            $grid->column('gift.attire.cate', '装扮类别');
+            $grid->column('gift_id');
+            $grid->column('num');
+            $grid->column('cost_paster');
+            $grid->column('created_at');
+            // $grid->column('updated_at')->sortable();
+            //
+            $grid->model()->orderByDesc("id");
+            $grid->disableActions();
+            $grid->disableBatchDelete();
+            $grid->disableRefreshButton();
+            $grid->disableCreateButton();
+            $grid->disableRowSelector();
+            // $grid->simplePaginate();
+            $grid->paginate(15);
+            $grid->addTableClass(['table-text-center']);
+            // $grid->disableToolbar();
+            $grid->filter(function ($filter) {
+                // 展开过滤器
+                $filter->panel();
+$filter->expand();
+                $filter->where('aid', function ($query) {
+                    $query->whereHas('account', function ($query) {
+                        $query->where('uid', $this->input);
+                    });
+                }, '用户UID')->width(2);
+                // $filter->equal('attire.cate', '类别')->select($this->cates)->width(2); // 设置编辑数据显示
+                $filter->equal('account_id','用户名')->select(\App\Models\Account::pluck('username','id'))->width(2);
+                $filter->equal('gift_id', '礼品ID')
+                    ->selectTable(GiftTable::make()) // 设置渲染类实例,并传递自定义参数
+                    ->title('礼品列表')
+                    ->dialogWidth('50%') // 弹窗宽度,默认 800px
+                    ->model(\App\Models\Gift::class, 'id', 'id')->width(2); // 设置编辑数据显示
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new GiftRecord(), function (Show $show) {
+            $show->field('id');
+            $show->field('account_id');
+            $show->field('gift_id');
+            $show->field('cost_pastera');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new GiftRecord(), function (Form $form) {
+            $form->display('id');
+            $form->text('account_id');
+            $form->text('gift_id');
+            $form->text('cost_pastera');
+        
+            $form->display('created_at');
+            $form->display('updated_at');
+        });
+    }
+}

+ 36 - 0
app/Admin/Controllers/HomeController.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Metrics\Examples;
+use App\Http\Controllers\Controller;
+use Dcat\Admin\Http\Controllers\Dashboard;
+use Dcat\Admin\Layout\Column;
+use Dcat\Admin\Layout\Content;
+use Dcat\Admin\Layout\Row;
+
+class HomeController extends Controller
+{
+    public function index(Content $content)
+    {
+        return $content
+            ->header('Dashboard')
+            ->description('Description...')
+            ->body(function (Row $row) {
+                $row->column(6, function (Column $column) {
+                    $column->row(Dashboard::title());
+                    $column->row(new Examples\Tickets());
+                });
+
+                $row->column(6, function (Column $column) {
+                    $column->row(function (Row $row) {
+                        $row->column(6, new Examples\NewUsers());
+                        $row->column(6, new Examples\NewDevices());
+                    });
+
+                    $column->row(new Examples\Sessions());
+                    $column->row(new Examples\ProductOrders());
+                });
+            });
+    }
+}

+ 85 - 0
app/Admin/Controllers/LiveRoomController.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\LiveRoom;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class LiveRoomController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new LiveRoom(), function (Grid $grid) {
+            $grid->column('id')->sortable();
+            $grid->column('name');
+            $grid->column('img')->image(config("filesystems.disks.cosv5.url"),60,60);
+            $grid->column('short_name');
+            $grid->column('medal_name');
+            $grid->column('room_id');
+            $grid->column('sort')->editable(true);
+            $grid->column('is_show_share')->using(['隐藏','显示']);
+            // $grid->column('created_at');
+            $grid->column('updated_at')->sortable();
+        
+            $grid->enableDialogCreate();
+            $grid->setDialogFormDimensions('50%', '60%');
+            $grid->withBorder();
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                $actions->quickEdit(true);
+                $actions->disableEdit();
+                $actions->disableView();
+            });
+            $grid->model()->orderBy("sort","asc")->orderBy("id","asc");
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new LiveRoom(), function (Show $show) {
+            $show->field('id');
+            $show->field('name');
+            $show->field('img');
+            $show->field('short_name');
+            $show->field('room_id');
+            $show->field('sort');
+            $show->field('is_show_share');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new LiveRoom(), function (Form $form) {
+            // $form->display('id');
+            $form->text('name')->required();
+            $form->image('img')->autoUpload()->removable(false)->autoSave(false)->uniqueName()->required();
+            $form->text('short_name')->required();
+            $form->text('medal_name');
+            $form->text('room_id')->required();
+            $form->number('sort')->default(0)->help("显示的顺序,默认从小到大显示");
+            $form->switch('is_show_share')->help("用来控制在H5页面的试衣间上传皮肤后的弹窗中是否显示");
+       
+        });
+    }
+}

+ 74 - 0
app/Admin/Controllers/PackRecordController.php

@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\PackRecord;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class PackRecordController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new PackRecord(), function (Grid $grid) {
+            $grid->column('id')->sortable();
+            $grid->column('account_id');
+            $grid->column('gift_pack_id');
+            $grid->column('cost_coupons');
+            $grid->column('created_at');
+            $grid->column('updated_at')->sortable();
+        
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->where('aid', function ($query) {
+                    $query->whereHas('account', function ($query) {
+                        $query->where('uid', $this->input);
+                    });
+                }, '用户UID')->width(2);
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new PackRecord(), function (Show $show) {
+            $show->field('id');
+            $show->field('account_id');
+            $show->field('gift_pack_id');
+            $show->field('cost_coupons');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new PackRecord(), function (Form $form) {
+            $form->display('id');
+            $form->text('account_id');
+            $form->text('gift_pack_id');
+            $form->text('cost_coupons');
+        
+            $form->display('created_at');
+            $form->display('updated_at');
+        });
+    }
+}

+ 132 - 0
app/Admin/Controllers/PasterRecordController.php

@@ -0,0 +1,132 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\PasterRecord;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class PasterRecordController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new PasterRecord(['account']), function (Grid $grid) {
+            $grid->column('id');
+            $grid->column('account.avatar','用户头像')->image(config("filesystems.disks.cosv5.url"), 60, 60);
+            $grid->column('account.username','用户');
+            $grid->column('add_cnt');
+            $grid->column('type')->using(['','礼盒回收','礼品兑换']);
+            $grid->column('record','记录明细')->display(function($v) {
+                if($this->type == 1) {
+                    return '开盒记录';
+                } elseif($this->type == 2) {
+                    return '兑换记录';
+                }
+            })->modal(function ($modal) {
+                if($this->type == 1) {
+                    $modal->title('开礼盒记录');
+                    // 允许在闭包内返回异步加载类的实例
+                    if($this->box_record_id) {
+                        return \App\Admin\Renderable\BoxRecordTable::make(['id' => $this->box_record_id]);
+                    }
+                    return false; 
+                } elseif($this->type == 2) {
+                    $modal->title('礼品兑换记录');
+                    // 允许在闭包内返回异步加载类的实例
+                    if($this->gift_record_id) {
+                        return \App\Admin\Renderable\GiftRecordTable::make(['id' => $this->gift_record_id]);
+                    }
+                    return false; 
+                }
+            });
+            // $grid->column('gift_record_id');
+            // $grid->column('gift_record_id','兑换记录')->display('查看')->modal(function ($modal) {
+            //     $modal->title('礼品兑换记录');
+            //     // 允许在闭包内返回异步加载类的实例
+            //     if($this->gift_record_id) {
+            //         return \App\Admin\Renderable\GiftRecordTable::make(['id' => $this->gift_record_id]);
+            //     }
+            //     return false; 
+            // });
+            // $grid->column('box_record_id','开盒记录')->display('查看')->modal(function ($modal) {
+            //     $modal->title('开礼盒记录');
+            //     // 允许在闭包内返回异步加载类的实例
+            //     if($this->box_record_id) {
+            //         return \App\Admin\Renderable\BoxRecordTable::make(['id' => $this->box_record_id]);
+            //     }
+            //     return false; 
+            // });
+            // $grid->column('box_record_id');
+            $grid->column('day');
+            $grid->column('created_at');
+            // $grid->column('updated_at')->sortable();
+
+            $grid->model()->orderByDesc("id");
+            $grid->disableActions();
+            $grid->disableBatchDelete();
+            $grid->disableRefreshButton();
+            $grid->disableCreateButton();
+            $grid->disableRowSelector();
+            // $grid->simplePaginate();
+            $grid->paginate(15);
+            $grid->addTableClass(['table-text-center']);
+            // $grid->disableToolbar();
+            $grid->filter(function ($filter) {
+                // 展开过滤器
+                $filter->panel();
+$filter->expand();
+                // $filter->equal('attire.cate', '类别')->select($this->cates)->width(2); // 设置编辑数据显示
+                $filter->equal('account_id','用户名')->select(\App\Models\Account::pluck('username','id'))->width(3);
+                $filter->equal('type')->select([1=>'礼盒回收',2=>'礼品兑换'])->width(3); // 设置编辑数据显示
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new PasterRecord(), function (Show $show) {
+            $show->field('id');
+            $show->field('account_id');
+            $show->field('add_cnt');
+            $show->field('type');
+            $show->field('gift_id');
+            $show->field('day');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new PasterRecord(), function (Form $form) {
+            $form->display('id');
+            $form->text('account_id');
+            $form->text('add_cnt');
+            $form->text('type');
+            $form->text('gift_id');
+            $form->text('day');
+
+            $form->display('created_at');
+            $form->display('updated_at');
+        });
+    }
+}

+ 69 - 0
app/Admin/Controllers/ResourceController.php

@@ -0,0 +1,69 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\Resource;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class ResourceController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new Resource(), function (Grid $grid) {
+            // $grid->column('id')->sortable();
+            $grid->column('name');
+            $grid->column('src')->image(config("filesystems.disks.cosv5.url"), 100, 100);
+            $grid->column('src2','地址')->display(function() {
+                return \Storage::disk('cosv5')->url($this->src);
+            });
+            //
+            $grid->enableDialogCreate();
+            $grid->setDialogFormDimensions('50%', '50%');
+            $grid->withBorder();
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                $actions->quickEdit(true);
+                $actions->disableEdit();
+                $actions->disableView();
+            });
+            $grid->model()->orderByDesc("id");
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new Resource(), function (Show $show) {
+            $show->field('id');
+            $show->field('name');
+            $show->field('src');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new Resource(), function (Form $form) {
+            // $form->display('id');
+            $form->text('name')->required();
+            $form->image('src')->autoUpload()->removable(false)->autoSave(false)->uniqueName()->required();
+        });
+    }
+}

+ 74 - 0
app/Admin/Forms/CouponSet.php

@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Admin\Forms;
+
+use Dcat\Admin\Widgets\Form;
+use Dcat\Admin\Traits\LazyWidget;
+use Dcat\Admin\Contracts\LazyRenderable;
+
+// 礼劵设置
+class CouponSet extends Form implements LazyRenderable
+{
+    use LazyWidget;
+    /**
+     * Handle the form request.
+     *
+     * @param array $input
+     *
+     * @return mixed
+     */
+    public function handle(array $input)
+    {
+        //
+        $obj = \App\Models\Config::where("key", "coupon_configs")->first();
+        if(!$obj) {
+            $obj = new \App\Models\Config();
+            $obj->key = "coupon_configs";
+        }
+        $obj->val = json_encode($input);
+        $obj->save();
+        //
+        return $this
+            ->response()
+            ->success('修改成功')
+            ->refresh();
+    }
+
+    /**
+     * Build a form here.
+     */
+    public function form()
+    {
+        //
+        $this->text("img_title", "排期标题")->required();
+        $this->image("img", "排期图片")->uniqueName()->removable(false)->autoUpload()->required();
+        $this->text("desc_title", "规则标题")->required();
+        $this->textarea("desc", "规则文案")->required();
+        $this->textarea("pop_desc", "弹窗规则文案")->required();
+        //
+    }
+
+    /**
+     * The data of the form.
+     *
+     * @return array
+     */
+    public function default()
+    {
+        //
+        $obj = \App\Models\Config::where("key", "coupon_configs")->first();
+        if ($obj && $obj->val) {
+            $data = json_decode($obj->val, true);
+            if ($data) {
+                return $data;
+            }
+        }
+        return [
+            'img_title'=> '限定活动排期',
+            'img'=> '',
+            'desc_title'=> '如何获得更多礼劵?',
+            'desc'=> '',
+            'pop_desc'=> '',
+        ];
+    }
+}

+ 63 - 0
app/Admin/Forms/GiftBoxHit.php

@@ -0,0 +1,63 @@
+<?php
+
+namespace App\Admin\Forms;
+
+use Dcat\Admin\Widgets\Form;
+use Dcat\Admin\Traits\LazyWidget;
+use Dcat\Admin\Contracts\LazyRenderable;
+
+// 开礼盒保底设置
+class GiftBoxHit extends Form implements LazyRenderable
+{
+    use LazyWidget;
+    /**
+     * Handle the form request.
+     *
+     * @param array $input
+     *
+     * @return mixed
+     */
+    public function handle(array $input)
+    {
+        //
+        $obj = \App\Models\Config::where("key", "box_hit_cnt")->first();
+        if(!$obj) {
+            $obj = new \App\Models\Config();
+            $obj->key = "box_hit_cnt";
+        }
+        $obj->val = (int)$input['hit_cnt'];
+        $obj->save();
+        //
+        return $this
+            ->response()
+            ->success('修改成功')
+            ->refresh();
+    }
+
+    /**
+     * Build a form here.
+     */
+    public function form()
+    {
+        //
+        $this->number("hit_cnt", "保底次数")->required()->help("到保底次数前还未抽中SSR,则下次必中");
+        //
+    }
+
+    /**
+     * The data of the form.
+     *
+     * @return array
+     */
+    public function default()
+    {
+        //
+        return (new \App\Http\Controllers\BoxController())->getBoxHit(); 
+        // $obj = \App\Models\Config::where("key", "box_hit_cnt")->first();
+        // if ($obj && $obj->val) {
+        //     return  ['hit_cnt'=>(int)$obj->val];
+        // }
+        // //
+        // return config("avatar.box_hit_cnt");
+    }
+}

+ 69 - 0
app/Admin/Forms/LevelPaster.php

@@ -0,0 +1,69 @@
+<?php
+
+namespace App\Admin\Forms;
+
+use Dcat\Admin\Widgets\Form;
+use Dcat\Admin\Traits\LazyWidget;
+use Dcat\Admin\Contracts\LazyRenderable;
+
+// 修改礼盒不同级别回收的贴纸数
+class LevelPaster extends Form implements LazyRenderable
+{
+    use LazyWidget;
+    /**
+     * Handle the form request.
+     *
+     * @param array $input
+     *
+     * @return mixed
+     */
+    public function handle(array $input)
+    {
+        //
+        $obj = \App\Models\Config::where("key", "box_level_paster")->first();
+        if(!$obj) {
+            $obj = new \App\Models\Config();
+            $obj->key = "box_level_paster";
+        }
+        $obj->val = json_encode($input);
+        $obj->save();
+        //
+        return $this
+            ->response()
+            ->success('修改成功')
+            ->refresh();
+    }
+
+    /**
+     * Build a form here.
+     */
+    public function form()
+    {
+        //
+        $this->number("N", "N级")->required();
+        $this->number("R", "R级")->required();
+        $this->number("SR", "SR级")->required();
+        $this->number("SSR", "SSR级")->required();
+        //
+    }
+
+    /**
+     * The data of the form.
+     *
+     * @return array
+     */
+    public function default()
+    {
+        //
+        return (new \App\Http\Controllers\BoxController())->getLevelPaster(); 
+        // $obj = \App\Models\Config::where("key", "box_level_paster")->first();
+        // if ($obj && $obj->val) {
+        //     $data = json_decode($obj->val, true);
+        //     if ($data) {
+        //         return $data;
+        //     }
+        // }
+        // //
+        // return config("avatar.box_level_paster");
+    }
+}

+ 77 - 0
app/Admin/Forms/LevelPercent.php

@@ -0,0 +1,77 @@
+<?php
+
+namespace App\Admin\Forms;
+
+use Dcat\Admin\Widgets\Form;
+use Dcat\Admin\Traits\LazyWidget;
+use Dcat\Admin\Contracts\LazyRenderable;
+
+// 修改礼盒不同级别的概率和回收的贴纸数
+class LevelPercent extends Form implements LazyRenderable
+{
+    use LazyWidget;
+    /**
+     * Handle the form request.
+     *
+     * @param array $input
+     *
+     * @return mixed
+     */
+    public function handle(array $input)
+    {
+        //
+        $val = 0;
+        foreach($input as $k=>$v) {
+            $val += $v;
+        }
+        if($val !=100) {
+            return $this->response()->error('出错了,概率之和不等于100');
+        }
+        //
+        $obj = \App\Models\Config::where("key", "box_level_percent")->first();
+        if(!$obj) {
+            $obj = new \App\Models\Config();
+            $obj->key = "box_level_percent";
+        }
+        $obj->val = json_encode($input);
+        $obj->save();
+        //
+        return $this
+            ->response()
+            ->success('修改成功')
+            ->refresh();
+    }
+
+    /**
+     * Build a form here.
+     */
+    public function form()
+    {
+        //
+        $this->currency("N", "N级")->symbol('%')->required();
+        $this->currency("R", "R级")->symbol('%')->required();
+        $this->currency("SR", "SR级")->symbol('%')->required();
+        $this->currency("SSR", "SSR级")->symbol('%')->required();
+        //
+    }
+
+    /**
+     * The data of the form.
+     *
+     * @return array
+     */
+    public function default()
+    {
+        //
+        return (new \App\Http\Controllers\BoxController())->getLevelPercent(); 
+        // $obj = \App\Models\Config::where("key", "box_level_percent")->first();
+        // if ($obj && $obj->val) {
+        //     $data = json_decode($obj->val, true);
+        //     if ($data) {
+        //         return $data;
+        //     }
+        // }
+        // //
+        // return config("avatar.box_level_percent");
+    }
+}

+ 62 - 0
app/Admin/Forms/NewUserCoupon.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace App\Admin\Forms;
+
+use Dcat\Admin\Widgets\Form;
+use Dcat\Admin\Traits\LazyWidget;
+use Dcat\Admin\Contracts\LazyRenderable;
+
+// 新人礼包配置
+class NewUserCoupon extends Form implements LazyRenderable
+{
+    use LazyWidget;
+    /**
+     * Handle the form request.
+     *
+     * @param array $input
+     *
+     * @return mixed
+     */
+    public function handle(array $input)
+    {
+        //
+        $obj = \App\Models\Config::where("key", "new_user_coupon")->first();
+        if(!$obj) {
+            $obj = new \App\Models\Config();
+            $obj->key = "new_user_coupon";
+        }
+        $obj->val = (int)$input['coupon'];
+        $obj->save();
+        //
+        return $this
+            ->response()
+            ->success('修改成功')
+            ->refresh();
+    }
+
+    /**
+     * Build a form here.
+     */
+    public function form()
+    {
+        //
+        $this->number("coupon", "新人礼包")->required();
+        //
+    }
+
+    /**
+     * The data of the form.
+     *
+     * @return array
+     */
+    public function default()
+    {
+        //
+        $obj = \App\Models\Config::where("key", "new_user_coupon")->first(); 
+        if($obj) {
+            return ['coupon'=>$obj->val];
+        } else {
+            return ['coupon' => config("avatar.new_user_coupon")];
+        }
+    }
+}

+ 100 - 0
app/Admin/Metrics/Examples/NewDevices.php

@@ -0,0 +1,100 @@
+<?php
+
+namespace App\Admin\Metrics\Examples;
+
+use Dcat\Admin\Admin;
+use Dcat\Admin\Widgets\Metrics\Donut;
+
+class NewDevices extends Donut
+{
+    protected $labels = ['Desktop', 'Mobile'];
+
+    /**
+     * 初始化卡片内容
+     */
+    protected function init()
+    {
+        parent::init();
+
+        $color = Admin::color();
+        $colors = [$color->primary(), $color->alpha('blue2', 0.5)];
+
+        $this->title('New Devices');
+        $this->subTitle('Last 30 days');
+        $this->chartLabels($this->labels);
+        // 设置图表颜色
+        $this->chartColors($colors);
+    }
+
+    /**
+     * 渲染模板
+     *
+     * @return string
+     */
+    public function render()
+    {
+        $this->fill();
+
+        return parent::render();
+    }
+
+    /**
+     * 写入数据.
+     *
+     * @return void
+     */
+    public function fill()
+    {
+        $this->withContent(44.9, 28.6);
+
+        // 图表数据
+        $this->withChart([44.9, 28.6]);
+    }
+
+    /**
+     * 设置图表数据.
+     *
+     * @param array $data
+     *
+     * @return $this
+     */
+    public function withChart(array $data)
+    {
+        return $this->chart([
+            'series' => $data
+        ]);
+    }
+
+    /**
+     * 设置卡片头部内容.
+     *
+     * @param mixed $desktop
+     * @param mixed $mobile
+     *
+     * @return $this
+     */
+    protected function withContent($desktop, $mobile)
+    {
+        $blue = Admin::color()->alpha('blue2', 0.5);
+
+        $style = 'margin-bottom: 8px';
+        $labelWidth = 120;
+
+        return $this->content(
+            <<<HTML
+<div class="d-flex pl-1 pr-1 pt-1" style="{$style}">
+    <div style="width: {$labelWidth}px">
+        <i class="fa fa-circle text-primary"></i> {$this->labels[0]}
+    </div>
+    <div>{$desktop}</div>
+</div>
+<div class="d-flex pl-1 pr-1" style="{$style}">
+    <div style="width: {$labelWidth}px">
+        <i class="fa fa-circle" style="color: $blue"></i> {$this->labels[1]}
+    </div>
+    <div>{$mobile}</div>
+</div>
+HTML
+        );
+    }
+}

+ 108 - 0
app/Admin/Metrics/Examples/NewUsers.php

@@ -0,0 +1,108 @@
+<?php
+
+namespace App\Admin\Metrics\Examples;
+
+use Dcat\Admin\Widgets\Metrics\Line;
+use Illuminate\Http\Request;
+
+class NewUsers extends Line
+{
+    /**
+     * 初始化卡片内容
+     *
+     * @return void
+     */
+    protected function init()
+    {
+        parent::init();
+
+        $this->title('New Users');
+        $this->dropdown([
+            '7' => 'Last 7 Days',
+            '28' => 'Last 28 Days',
+            '30' => 'Last Month',
+            '365' => 'Last Year',
+        ]);
+    }
+
+    /**
+     * 处理请求
+     *
+     * @param Request $request
+     *
+     * @return mixed|void
+     */
+    public function handle(Request $request)
+    {
+        $generator = function ($len, $min = 10, $max = 300) {
+            for ($i = 0; $i <= $len; $i++) {
+                yield mt_rand($min, $max);
+            }
+        };
+
+        switch ($request->get('option')) {
+            case '365':
+                // 卡片内容
+                $this->withContent(mt_rand(1000, 5000).'k');
+                // 图表数据
+                $this->withChart(collect($generator(30))->toArray());
+                break;
+            case '30':
+                // 卡片内容
+                $this->withContent(mt_rand(400, 1000).'k');
+                // 图表数据
+                $this->withChart(collect($generator(30))->toArray());
+                break;
+            case '28':
+                // 卡片内容
+                $this->withContent(mt_rand(400, 1000).'k');
+                // 图表数据
+                $this->withChart(collect($generator(28))->toArray());
+                break;
+            case '7':
+            default:
+                // 卡片内容
+                $this->withContent('89.2k');
+                // 图表数据
+                $this->withChart([28, 40, 36, 52, 38, 60, 55,]);
+        }
+    }
+
+    /**
+     * 设置图表数据.
+     *
+     * @param array $data
+     *
+     * @return $this
+     */
+    public function withChart(array $data)
+    {
+        return $this->chart([
+            'series' => [
+                [
+                    'name' => $this->title,
+                    'data' => $data,
+                ],
+            ],
+        ]);
+    }
+
+    /**
+     * 设置卡片内容.
+     *
+     * @param string $content
+     *
+     * @return $this
+     */
+    public function withContent($content)
+    {
+        return $this->content(
+            <<<HTML
+<div class="d-flex justify-content-between align-items-center mt-1" style="margin-bottom: 2px">
+    <h2 class="ml-1 font-lg-1">{$content}</h2>
+    <span class="mb-0 mr-1 text-80">{$this->title}</span>
+</div>
+HTML
+        );
+    }
+}

+ 114 - 0
app/Admin/Metrics/Examples/ProductOrders.php

@@ -0,0 +1,114 @@
+<?php
+
+namespace App\Admin\Metrics\Examples;
+
+use Dcat\Admin\Widgets\Metrics\Round;
+use Illuminate\Http\Request;
+
+class ProductOrders extends Round
+{
+    /**
+     * 初始化卡片内容
+     */
+    protected function init()
+    {
+        parent::init();
+
+        $this->title('Product Orders');
+        $this->chartLabels(['Finished', 'Pending', 'Rejected']);
+        $this->dropdown([
+            '7' => 'Last 7 Days',
+            '28' => 'Last 28 Days',
+            '30' => 'Last Month',
+            '365' => 'Last Year',
+        ]);
+    }
+
+    /**
+     * 处理请求
+     *
+     * @param Request $request
+     *
+     * @return mixed|void
+     */
+    public function handle(Request $request)
+    {
+        switch ($request->get('option')) {
+            case '365':
+            case '30':
+            case '28':
+            case '7':
+            default:
+                // 卡片内容
+                $this->withContent(23043, 14658, 4758);
+
+                // 图表数据
+                $this->withChart([70, 52, 26]);
+
+                // 总数
+                $this->chartTotal('Total', 344);
+        }
+    }
+
+    /**
+     * 设置图表数据.
+     *
+     * @param array $data
+     *
+     * @return $this
+     */
+    public function withChart(array $data)
+    {
+        return $this->chart([
+            'series' => $data,
+        ]);
+    }
+
+    /**
+     * 卡片内容.
+     *
+     * @param int $finished
+     * @param int $pending
+     * @param int $rejected
+     *
+     * @return $this
+     */
+    public function withContent($finished, $pending, $rejected)
+    {
+        return $this->content(
+            <<<HTML
+<div class="col-12 d-flex flex-column flex-wrap text-center" style="max-width: 220px">
+    <div class="chart-info d-flex justify-content-between mb-1 mt-2" >
+          <div class="series-info d-flex align-items-center">
+              <i class="fa fa-circle-o text-bold-700 text-primary"></i>
+              <span class="text-bold-600 ml-50">Finished</span>
+          </div>
+          <div class="product-result">
+              <span>{$finished}</span>
+          </div>
+    </div>
+
+    <div class="chart-info d-flex justify-content-between mb-1">
+          <div class="series-info d-flex align-items-center">
+              <i class="fa fa-circle-o text-bold-700 text-warning"></i>
+              <span class="text-bold-600 ml-50">Pending</span>
+          </div>
+          <div class="product-result">
+              <span>{$pending}</span>
+          </div>
+    </div>
+
+     <div class="chart-info d-flex justify-content-between mb-1">
+          <div class="series-info d-flex align-items-center">
+              <i class="fa fa-circle-o text-bold-700 text-danger"></i>
+              <span class="text-bold-600 ml-50">Rejected</span>
+          </div>
+          <div class="product-result">
+              <span>{$rejected}</span>
+          </div>
+    </div>
+</div>
+HTML
+        );
+    }
+}

+ 117 - 0
app/Admin/Metrics/Examples/Sessions.php

@@ -0,0 +1,117 @@
+<?php
+
+namespace App\Admin\Metrics\Examples;
+
+use Dcat\Admin\Admin;
+use Dcat\Admin\Widgets\Metrics\Bar;
+use Illuminate\Http\Request;
+
+class Sessions extends Bar
+{
+    /**
+     * 初始化卡片内容
+     */
+    protected function init()
+    {
+        parent::init();
+
+        $color = Admin::color();
+
+        $dark35 = $color->dark35();
+
+        // 卡片内容宽度
+        $this->contentWidth(5, 7);
+        // 标题
+        $this->title('Avg Sessions');
+        // 设置下拉选项
+        $this->dropdown([
+            '7' => 'Last 7 Days',
+            '28' => 'Last 28 Days',
+            '30' => 'Last Month',
+            '365' => 'Last Year',
+        ]);
+        // 设置图表颜色
+        $this->chartColors([
+            $dark35,
+            $dark35,
+            $color->primary(),
+            $dark35,
+            $dark35,
+            $dark35
+        ]);
+    }
+
+    /**
+     * 处理请求
+     *
+     * @param Request $request
+     *
+     * @return mixed|void
+     */
+    public function handle(Request $request)
+    {
+        switch ($request->get('option')) {
+            case '7':
+            default:
+                // 卡片内容
+                $this->withContent('2.7k', '+5.2%');
+
+                // 图表数据
+                $this->withChart([
+                    [
+                        'name' => 'Sessions',
+                        'data' => [75, 125, 225, 175, 125, 75, 25],
+                    ],
+                ]);
+        }
+    }
+
+    /**
+     * 设置图表数据.
+     *
+     * @param array $data
+     *
+     * @return $this
+     */
+    public function withChart(array $data)
+    {
+        return $this->chart([
+            'series' => $data,
+        ]);
+    }
+
+    /**
+     * 设置卡片内容.
+     *
+     * @param string $title
+     * @param string $value
+     * @param string $style
+     *
+     * @return $this
+     */
+    public function withContent($title, $value, $style = 'success')
+    {
+        // 根据选项显示
+        $label = strtolower(
+            $this->dropdown[request()->option] ?? 'last 7 days'
+        );
+
+        $minHeight = '183px';
+
+        return $this->content(
+            <<<HTML
+<div class="d-flex p-1 flex-column justify-content-between" style="padding-top: 0;width: 100%;height: 100%;min-height: {$minHeight}">
+    <div class="text-left">
+        <h1 class="font-lg-2 mt-2 mb-0">{$title}</h1>
+        <h5 class="font-medium-2" style="margin-top: 10px;">
+            <span class="text-{$style}">{$value} </span>
+            <span>vs {$label}</span>
+        </h5>
+    </div>
+
+    <a href="#" class="btn btn-primary shadow waves-effect waves-light">View Details <i class="feather icon-chevrons-right"></i></a>
+</div>
+HTML
+        );
+    }
+}

+ 116 - 0
app/Admin/Metrics/Examples/Tickets.php

@@ -0,0 +1,116 @@
+<?php
+
+namespace App\Admin\Metrics\Examples;
+
+use Dcat\Admin\Widgets\Metrics\RadialBar;
+use Illuminate\Http\Request;
+
+class Tickets extends RadialBar
+{
+    /**
+     * 初始化卡片内容
+     */
+    protected function init()
+    {
+        parent::init();
+
+        $this->title('Tickets');
+        $this->height(400);
+        $this->chartHeight(300);
+        $this->chartLabels('Completed Tickets');
+        $this->dropdown([
+            '7' => 'Last 7 Days',
+            '28' => 'Last 28 Days',
+            '30' => 'Last Month',
+            '365' => 'Last Year',
+        ]);
+    }
+
+    /**
+     * 处理请求
+     *
+     * @param Request $request
+     *
+     * @return mixed|void
+     */
+    public function handle(Request $request)
+    {
+        switch ($request->get('option')) {
+            case '365':
+            case '30':
+            case '28':
+            case '7':
+            default:
+                // 卡片内容
+                $this->withContent(162);
+                // 卡片底部
+                $this->withFooter(29, 63, '1d');
+                // 图表数据
+                $this->withChart(83);
+        }
+    }
+
+    /**
+     * 设置图表数据.
+     *
+     * @param int $data
+     *
+     * @return $this
+     */
+    public function withChart(int $data)
+    {
+        return $this->chart([
+            'series' => [$data],
+        ]);
+    }
+
+    /**
+     * 卡片内容
+     *
+     * @param string $content
+     *
+     * @return $this
+     */
+    public function withContent($content)
+    {
+        return $this->content(
+            <<<HTML
+<div class="d-flex flex-column flex-wrap text-center">
+    <h1 class="font-lg-2 mt-2 mb-0">{$content}</h1>
+    <small>Tickets</small>
+</div>
+HTML
+        );
+    }
+
+    /**
+     * 卡片底部内容.
+     *
+     * @param string $new
+     * @param string $open
+     * @param string $response
+     *
+     * @return $this
+     */
+    public function withFooter($new, $open, $response)
+    {
+        return $this->footer(
+            <<<HTML
+<div class="d-flex justify-content-between p-1" style="padding-top: 0!important;">
+    <div class="text-center">
+        <p>New Tickets</p>
+        <span class="font-lg-1">{$new}</span>
+    </div>
+    <div class="text-center">
+        <p>Open Tickets</p>
+        <span class="font-lg-1">{$open}</span>
+    </div>
+    <div class="text-center">
+        <p>Response Time</p>
+        <span class="font-lg-1">{$response}</span>
+    </div>
+</div>
+HTML
+        );
+    }
+}

+ 129 - 0
app/Admin/Metrics/Examples/TotalUsers.php

@@ -0,0 +1,129 @@
+<?php
+
+namespace App\Admin\Metrics\Examples;
+
+use Dcat\Admin\Widgets\Metrics\Card;
+use Illuminate\Contracts\Support\Renderable;
+use Illuminate\Http\Request;
+
+class TotalUsers extends Card
+{
+    /**
+     * 卡片底部内容.
+     *
+     * @var string|Renderable|\Closure
+     */
+    protected $footer;
+
+    /**
+     * 初始化卡片.
+     */
+    protected function init()
+    {
+        parent::init();
+
+        $this->title('Total Users');
+        $this->dropdown([
+            '7' => 'Last 7 Days',
+            '28' => 'Last 28 Days',
+            '30' => 'Last Month',
+            '365' => 'Last Year',
+        ]);
+    }
+
+    /**
+     * 处理请求.
+     *
+     * @param Request $request
+     *
+     * @return void
+     */
+    public function handle(Request $request)
+    {
+        switch ($request->get('option')) {
+            case '365':
+                $this->content(mt_rand(600, 1500));
+                $this->down(mt_rand(1, 30));
+                break;
+            case '30':
+                $this->content(mt_rand(170, 250));
+                $this->up(mt_rand(12, 50));
+                break;
+            case '28':
+                $this->content(mt_rand(155, 200));
+                $this->up(mt_rand(5, 50));
+                break;
+            case '7':
+            default:
+                $this->content(143);
+                $this->up(15);
+        }
+    }
+
+    /**
+     * @param int $percent
+     *
+     * @return $this
+     */
+    public function up($percent)
+    {
+        return $this->footer(
+            "<i class=\"feather icon-trending-up text-success\"></i> {$percent}% Increase"
+        );
+    }
+
+    /**
+     * @param int $percent
+     *
+     * @return $this
+     */
+    public function down($percent)
+    {
+        return $this->footer(
+            "<i class=\"feather icon-trending-down text-danger\"></i> {$percent}% Decrease"
+        );
+    }
+
+    /**
+     * 设置卡片底部内容.
+     *
+     * @param string|Renderable|\Closure $footer
+     *
+     * @return $this
+     */
+    public function footer($footer)
+    {
+        $this->footer = $footer;
+
+        return $this;
+    }
+
+    /**
+     * 渲染卡片内容.
+     *
+     * @return string
+     */
+    public function renderContent()
+    {
+        $content = parent::renderContent();
+
+        return <<<HTML
+<div class="d-flex justify-content-between align-items-center mt-1" style="margin-bottom: 2px">
+    <h2 class="ml-1 font-lg-1">{$content}</h2>
+</div>
+<div class="ml-1 mt-1 font-weight-bold text-80">
+    {$this->renderFooter()}
+</div>
+HTML;
+    }
+
+    /**
+     * 渲染卡片底部内容.
+     *
+     * @return string
+     */
+    public function renderFooter()
+    {
+        return $this->toString($this->footer);
+    }
+}

+ 55 - 0
app/Admin/Renderable/AttireTable.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace App\Admin\Renderable;
+
+use Dcat\Admin\Grid;
+use Dcat\Admin\Grid\LazyRenderable;
+use App\Admin\Repositories\Attire;
+
+class AttireTable extends LazyRenderable
+{
+    public $cates = [
+        '套装' => '套装',
+        '皮肤' => '皮肤',
+    ];
+    public $levels = [
+        'N' => 'N',
+        'R' => 'R',
+        'SR' => 'SR',
+        'SSR' => 'SSR',
+    ];
+
+    public function grid(): Grid
+    {
+
+        // 获取外部传递的参数
+        $id = $this->id;
+
+        return Grid::make(new Attire(), function (Grid $grid) {
+            //
+            $grid->column('name');
+            $grid->column('cate', '类别');
+            $grid->column('img_1', '正面图片')->image(config("filesystems.disks.cosv5.url"), 60, 60);
+            $grid->column('img_2', '背面图片')->image(config("filesystems.disks.cosv5.url"), 60, 60);
+
+            $grid->withBorder();
+            $grid->model()->orderByDesc("id");
+            $grid->paginate(10);
+            $grid->disableActions();
+            $grid->rowSelector()->titleColumn('name');
+            //
+            $grid->filter(function ($filter) {
+                // 展开过滤器
+                // $filter->panel();
+$filter->expand();
+                $filter->expand();
+                $filter->withoutInputBorder();
+                // 在这里添加字段过滤器
+                // $filter->equal('id')->width(2);
+                $filter->equal('name', '名称')->width(3);
+                $filter->equal('cate', '类别')->select($this->cates)->width(3);
+                $filter->equal('level', '等级')->select($this->levels)->width(3);
+            });
+        });
+    }
+}

+ 48 - 0
app/Admin/Renderable/BoxRecordAttiresTable.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace App\Admin\Renderable;
+
+use Dcat\Admin\Support\LazyRenderable;
+use Dcat\Admin\Widgets\Table;
+
+class BoxRecordAttiresTable extends LazyRenderable
+{
+
+    //
+    public function render() {
+        // 获取ID
+        $ids = explode(",",$this->ids);
+
+        $tmp = \App\Models\GiftBox::withTrashed()
+            ->whereIn('id', $ids)
+            ->with(['attire'])
+            ->get()
+            ->toArray();
+        //
+        $tmp = array_column($tmp, null, 'id');
+        //
+        $data = [];
+        foreach($ids as $id) {
+            $t = [
+                'id' => $tmp[$id]['attire_id'],
+                'name' => $tmp[$id]['attire']['name'],
+                'level' => $tmp[$id]['attire']['level'],
+                'img_1' => "<img src='".\Storage::disk('cosv5')->url($tmp[$id]['attire']["img_1"])."' style='width:60px;height:auto;'/>",
+                'img_2' => "<img src='".\Storage::disk('cosv5')->url($tmp[$id]['attire']["img_2"])."' style='width:60px;height:auto;'/>",
+                'cate' => $tmp[$id]['attire']['cate'],
+            ];
+            $data[] = $t;
+        }
+        //
+        $titles = [
+            '装扮ID',
+            '名称',
+            '级别',
+            '正面图片',
+            '背面图片',
+            '类别',
+        ];
+
+        return Table::make($titles, $data);
+    }
+}

+ 48 - 0
app/Admin/Renderable/BoxRecordRetrieveAttiresTable.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace App\Admin\Renderable;
+
+use Dcat\Admin\Support\LazyRenderable;
+use Dcat\Admin\Widgets\Table;
+
+class BoxRecordRetrieveAttiresTable extends LazyRenderable
+{
+
+    //
+    public function render() {
+        // 获取ID
+        $ids = explode(",",$this->ids);
+
+        $tmp = \App\Models\GiftBox::withTrashed()
+            ->whereIn('id', $ids)
+            ->with(['attire'])
+            ->get()
+            ->toArray();
+        //
+        $tmp = array_column($tmp, null, 'id');
+        //
+        $data = [];
+        foreach($ids as $id) {
+            $t = [
+                'id' => $tmp[$id]['attire_id'],
+                'name' => $tmp[$id]['attire']['name'],
+                'level' => $tmp[$id]['attire']['level'],
+                'img_1' => "<img src='".\Storage::disk('cosv5')->url($tmp[$id]['attire']["img_1"])."' style='width:60px;height:auto;'/>",
+                'img_2' => "<img src='".\Storage::disk('cosv5')->url($tmp[$id]['attire']["img_2"])."' style='width:60px;height:auto;'/>",
+                'cate' => $tmp[$id]['attire']['cate'],
+            ];
+            $data[] = $t;
+        }
+        //
+        $titles = [
+            '装扮ID',
+            '名称',
+            '级别',
+            '正面图片',
+            '背面图片',
+            '类别',
+        ];
+
+        return Table::make($titles, $data);
+    }
+}

+ 52 - 0
app/Admin/Renderable/BoxRecordTable.php

@@ -0,0 +1,52 @@
+<?php
+
+namespace App\Admin\Renderable;
+
+use Dcat\Admin\Grid;
+use Dcat\Admin\Grid\LazyRenderable;
+use App\Admin\Repositories\BoxRecord;
+
+class BoxRecordTable extends LazyRenderable
+{
+    //
+    public function grid(): Grid
+    {
+        //
+        return Grid::make(new BoxRecord(['account']), function (Grid $grid) {
+            $grid->column('id')->sortable();
+            $grid->column('account.username','用户名');
+            $grid->column('num','开盒数量');
+            $grid->column('box_ids','获得装扮')->display(function($v) {
+                return "点击查看(".($v? count(explode(",", $v)): 0).")";
+            })->expand(function () {
+                if($this->box_ids) {
+                    return \App\Admin\Renderable\BoxRecordAttiresTable::make(["ids"=>$this->box_ids]);
+                }
+                return "";
+            });
+            $grid->column('retrieve_pasters','回收贴纸数');
+            $grid->column('retrieve_box_ids','回收礼盒')->display(function($v) {
+                return "点击查看(".($v? count(explode(",", $v)):0).")";
+            })->expand(function () {
+                if($this->retrieve_box_ids) {
+                    return \App\Admin\Renderable\BoxRecordRetrieveAttiresTable::make(["ids"=>$this->retrieve_box_ids]);
+                }
+                return "";
+            });
+            $grid->column('cost_coupons','消耗礼劵');
+            $grid->column('created_at','创建时间');
+        
+            $grid->model()->where("id",$this->id);
+            $grid->disableActions();
+            $grid->disableBatchDelete();
+            $grid->disableRefreshButton();
+            $grid->disableCreateButton();
+            $grid->disableRowSelector();
+            $grid->simplePaginate();
+            $grid->paginate(15);
+            $grid->addTableClass(['table-text-center']);
+            $grid->disableToolbar();
+            $grid->disablePagination();
+        });
+    }
+}

+ 47 - 0
app/Admin/Renderable/GiftRecordTable.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace App\Admin\Renderable;
+
+use Dcat\Admin\Grid;
+use Dcat\Admin\Grid\LazyRenderable;
+use App\Admin\Repositories\GiftRecord;
+
+class GiftRecordTable extends LazyRenderable
+{
+    //
+    public function grid(): Grid
+    {
+        //
+        return Grid::make(new GiftRecord(['account','gift.attire']), function (Grid $grid) {
+            $grid->column('id');
+            $grid->column('account.username','用户');
+            $grid->column('gift.type','礼品类型')->using(['','礼劵','装扮'])->label();
+            // $grid->column('attire_id');
+            $grid->column('gift.attire.name', '装扮名称');
+            $grid->column('gift.attire.img_1', '礼品图片')->display(function($v) {
+                if($this->gift->type == 1) {
+                    return "<img src='".\Storage::disk('cosv5')->url($this->gift->img)."' style='height:60px;width:auto;' />";
+                } else {
+                    return "<img src='".\Storage::disk('cosv5')->url($v)."' style='height:60px;width:auto;' />";
+                }
+            });
+            $grid->column('gift.attire.cate', '装扮类别');
+            $grid->column('gift_id','礼品ID');
+            $grid->column('num','兑换数量');
+            $grid->column('cost_paster','兑换贴纸数');
+            $grid->column('created_at','创建时间');
+        
+            $grid->model()->where("id",$this->id);
+            $grid->disableActions();
+            $grid->disableBatchDelete();
+            $grid->disableRefreshButton();
+            $grid->disableCreateButton();
+            $grid->disableRowSelector();
+            $grid->simplePaginate();
+            $grid->paginate(15);
+            $grid->addTableClass(['table-text-center']);
+            $grid->disableToolbar();
+            $grid->disablePagination();
+        });
+    }
+}

+ 53 - 0
app/Admin/Renderable/GiftTable.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace App\Admin\Renderable;
+
+use Dcat\Admin\Grid;
+use Dcat\Admin\Grid\LazyRenderable;
+use App\Admin\Repositories\Gift;
+
+class GiftTable extends LazyRenderable
+{
+    public $cates = [
+        '套装' => '套装',
+        '皮肤' => '皮肤',
+    ];
+
+    public function grid(): Grid
+    {
+
+        // 获取外部传递的参数
+        $id = $this->id;
+
+        return Grid::make(new Gift(), function (Grid $grid) {
+            //
+            $grid->column('id');
+            // $grid->column('name');
+            $grid->column('type')->using(['','礼劵','装扮'])->label();
+            // $grid->column('attire_id');
+            $grid->column('attire.name', '装扮名称');
+            $grid->column('attire.img_1', '图片')->display(function($v) {
+                if($this->type == 1) {
+                    return "<img src='".\Storage::disk('cosv5')->url($this->img)."' style='height:60px;width:auto;' />";
+                } else {
+                    return "<img src='".\Storage::disk('cosv5')->url($v)."' style='height:60px;width:auto;' />";
+                }
+            });
+            $grid->column('attire.cate', '装扮类别');
+            $grid->column('cost_pasters');
+            $grid->column('limit');
+            $grid->column('sort')->editable(true);
+        
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->equal('id');
+            });
+            $grid->model()->orderBy("sort");
+
+            $grid->enableDialogCreate();
+            $grid->setDialogFormDimensions('50%', '60%');
+            $grid->withBorder();
+            $grid->addTableClass(['table-text-center']);
+            $grid->disableActions();
+        });
+    }
+}

+ 48 - 0
app/Admin/Renderable/PackRecordTable.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace App\Admin\Renderable;
+
+use Dcat\Admin\Grid;
+use Dcat\Admin\Grid\LazyRenderable;
+use App\Admin\Repositories\PackRecord;
+
+class PackRecordTable extends LazyRenderable
+{
+
+    public function grid(): Grid
+    {
+
+        return Grid::make(new PackRecord(['account','giftPack']), function (Grid $grid) {
+            //
+            $grid->column('account.uid','用户UID');
+            $grid->column('account.avatar','用户头像')->image(config("filesystems.disks.cosv5.url"), 60, 60);
+            $grid->column('account.username','用户名称')->display(function($v) {
+                return "<a href='/admin/accounts?id={$this->account_id}' target='_blank'>{$v}</a>";
+            });
+            $grid->column('giftPack.name', '礼包名称');
+            $grid->column('cost_coupons','花费礼劵');
+            $grid->column('created_at','兑换时间');
+
+            $grid->withBorder();
+            $grid->model()->orderByDesc("id");
+            $grid->paginate(10);
+            $grid->disableActions();
+            $grid->rowSelector()->titleColumn('name');
+            //
+            $grid->filter(function (Grid\Filter $filter) {
+                // 展开过滤器
+                $filter->panel();
+                $filter->expand();
+                $filter->withoutInputBorder();
+                // 在这里添加字段过滤器
+                // $filter->equal('id')->width(2);
+                $filter->where('aid', function ($query) {
+                    $query->whereHas('account', function ($query) {
+                        $query->where('uid', $this->input);
+                    });
+                }, '用户UID')->width(3);
+                $filter->equal('account_id','用户名')->select(\App\Models\Account::pluck('username','id'))->width(3);
+            });
+        });
+    }
+}

+ 16 - 0
app/Admin/Repositories/Account.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\Account as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class Account extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/Attire.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\Attire as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class Attire extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/BoxRecord.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\BoxRecord as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class BoxRecord extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/Config.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\Config as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class Config extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/CouponRecord.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\CouponRecord as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class CouponRecord extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/FittingRoom.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\FittingRoom as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class FittingRoom extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/Gift.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\Gift as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class Gift extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/GiftBox.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\GiftBox as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class GiftBox extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/GiftPack.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\GiftPack as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class GiftPack extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/GiftRecord.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\GiftRecord as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class GiftRecord extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/LiveRoom.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\LiveRoom as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class LiveRoom extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/PackRecord.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\PackRecord as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class PackRecord extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/PasterRecord.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\PasterRecord as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class PasterRecord extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 16 - 0
app/Admin/Repositories/Resource.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\Resource as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class Resource extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+}

+ 28 - 0
app/Admin/bootstrap.php

@@ -0,0 +1,28 @@
+<?php
+
+use Dcat\Admin\Admin;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid\Filter;
+use Dcat\Admin\Show;
+
+/**
+ * Dcat-admin - admin builder based on Laravel.
+ * @author jqh <https://github.com/jqhph>
+ *
+ * Bootstraper for Admin.
+ *
+ * Here you can remove builtin form field:
+ *
+ * extend custom field:
+ * Dcat\Admin\Form::extend('php', PHPEditor::class);
+ * Dcat\Admin\Grid\Column::extend('php', PHPEditor::class);
+ * Dcat\Admin\Grid\Filter::extend('php', PHPEditor::class);
+ *
+ * Or require js and css assets:
+ * Admin::css('/packages/prettydocs/css/styles.css');
+ * Admin::js('/packages/prettydocs/js/main.js');
+ *
+ */
+Admin::asset()->alias('@nunito', null, '');
+Admin::asset()->alias('@montserrat', null, '');

+ 29 - 0
app/Admin/routes.php

@@ -0,0 +1,29 @@
+<?php
+
+use Illuminate\Routing\Router;
+use Illuminate\Support\Facades\Route;
+use Dcat\Admin\Admin;
+
+Admin::routes();
+
+Route::group([
+    'prefix'        => config('admin.route.prefix'),
+    'namespace'     => config('admin.route.namespace'),
+    'middleware'    => config('admin.route.middleware'),
+], function (Router $router) {
+
+    $router->redirect('/', '/admin/gift_boxes');
+    $router->resource('accounts', 'AccountController');
+    $router->resource('coupon_records', 'CouponRecordController');
+    $router->resource('paster_records', 'PasterRecordController');
+    $router->resource('attires', 'AttireController');
+    $router->resource('gift_boxes', 'GiftBoxController');
+    $router->resource('fitting_rooms', 'FittingRoomController');
+    $router->resource('gift_packs', 'GiftPackController');
+    $router->resource('confs', 'ConfigController');
+    $router->resource('gifts', 'GiftController');
+    $router->resource('box_records', 'BoxRecordController');
+    $router->resource('gift_records', 'GiftRecordController');
+    $router->resource('resources', 'ResourceController');
+    $router->resource('live_rooms', 'LiveRoomController');
+});

+ 126 - 0
app/Console/Commands/SyncOss.php

@@ -0,0 +1,126 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Storage;
+
+class SyncOss extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'sync:oss';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '图片同步到腾讯云OSS';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        // 同步头像
+        // $this->syncAvatar();
+        // $this->syncAttires();
+        // $this->syncGift();
+        // $this->syncPack();
+        // $this->syncLiveRoom();
+        // $this->syncResource();
+        return 0;
+    }
+
+    public function syncAvatar() {
+        $avatars = \App\Models\Account::all();
+        $avatars->each(function ($item, $key) {
+            $v = Storage::disk("cosv5")->put($item->avatar, Storage::disk('admin')->get($item->avatar));
+            if(!$v) {
+                dump("出错了".$item->avatar);
+            } else {
+                dump("ok".$item->avatar);
+            }
+        });
+    }
+    public function syncAttires() {
+        $avatars = \App\Models\Attire::all();
+        $avatars->each(function ($item, $key) {
+            $v = Storage::disk("cosv5")->put($item->img_1, Storage::disk('admin')->get($item->img_1));
+            if(!$v) {
+                dump("出错了".$item->img_1);
+            } else {
+                dump("ok".$item->img_1);
+            }
+            $v = Storage::disk("cosv5")->put($item->img_2, Storage::disk('admin')->get($item->img_2));
+            if(!$v) {
+                dump("出错了".$item->img_2);
+            } else {
+                dump("ok".$item->img_2);
+            }
+        });
+    }
+    public function syncGift() {
+        $avatars = \App\Models\Gift::all();
+        $avatars->each(function ($item, $key) {
+            $v = Storage::disk("cosv5")->put($item->img, Storage::disk('admin')->get($item->img));
+            if(!$v) {
+                dump("出错了".$item->img);
+            } else {
+                dump("ok".$item->img);
+            }
+        });
+    }
+
+    public function syncPack() {
+        $avatars = \App\Models\GiftPack::all();
+        $avatars->each(function ($item, $key) {
+            $v = Storage::disk("cosv5")->put($item->img, Storage::disk('admin')->get($item->img));
+            if(!$v) {
+                dump("出错了-".$item->img);
+            } else {
+                dump("ok-".$item->img);
+            }
+        });
+    }
+
+    public function syncLiveRoom() {
+        $avatars = \App\Models\LiveRoom::all();
+        $avatars->each(function ($item, $key) {
+            $v = Storage::disk("cosv5")->put($item->img, Storage::disk('admin')->get($item->img));
+            if(!$v) {
+                dump("出错了-".$item->img);
+            } else {
+                dump("ok-".$item->img);
+            }
+        });
+    }
+
+    public function syncResource() {
+        $avatars = \App\Models\Resource::all();
+        $avatars->each(function ($item, $key) {
+            $v = Storage::disk("cosv5")->put($item->src, Storage::disk('admin')->get($item->src));
+            if(!$v) {
+                dump("出错了-".$item->src);
+            } else {
+                dump("ok-".$item->src);
+            }
+        });
+    }
+}

+ 59 - 0
app/Console/Commands/TruncateUserDataCommand.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Redis;
+
+// 清空用户相关数据表
+class TruncateUserDataCommand extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'truncate:users';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '清空用户相关数据';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        // 临时测试
+        // $o = \App\Models\Account::where("username","kailuo99")->first();
+        // $o->delete();
+        // \App\Models\FittingRoom::where("account_id", $o->id)->delete();
+        //
+        \DB::table('accounts')->truncate();
+        \DB::table('box_records')->truncate();
+        \DB::table('coupon_records')->truncate();
+        \DB::table('gift_records')->truncate();
+        \DB::table('pack_records')->truncate();
+        \DB::table('paster_records')->truncate();
+        \DB::table('fitting_rooms')->truncate();
+        // 清空redis
+        // Redis::flushdb();
+        //
+        return 0;
+    }
+}

+ 32 - 0
app/Console/Kernel.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace App\Console;
+
+use Illuminate\Console\Scheduling\Schedule;
+use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
+
+class Kernel extends ConsoleKernel
+{
+    /**
+     * Define the application's command schedule.
+     *
+     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
+     * @return void
+     */
+    protected function schedule(Schedule $schedule)
+    {
+        // $schedule->command('inspire')->hourly();
+    }
+
+    /**
+     * Register the commands for the application.
+     *
+     * @return void
+     */
+    protected function commands()
+    {
+        $this->load(__DIR__.'/Commands');
+
+        require base_path('routes/console.php');
+    }
+}

+ 41 - 0
app/Exceptions/Handler.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace App\Exceptions;
+
+use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
+use Throwable;
+
+class Handler extends ExceptionHandler
+{
+    /**
+     * A list of the exception types that are not reported.
+     *
+     * @var array<int, class-string<Throwable>>
+     */
+    protected $dontReport = [
+        //
+    ];
+
+    /**
+     * A list of the inputs that are never flashed for validation exceptions.
+     *
+     * @var array<int, string>
+     */
+    protected $dontFlash = [
+        'current_password',
+        'password',
+        'password_confirmation',
+    ];
+
+    /**
+     * Register the exception handling callbacks for the application.
+     *
+     * @return void
+     */
+    public function register()
+    {
+        $this->reportable(function (Throwable $e) {
+            //
+        });
+    }
+}

+ 213 - 0
app/Http/Controllers/AccountController.php

@@ -0,0 +1,213 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Redis;
+
+class AccountController extends Controller
+{
+    //
+    // 获取用户信息
+    public function userinfo(Request $request) {
+        //
+        $user = unserialize($request->get("account"));
+        //
+        $status = 2; // 1:未验证 2:已登录
+        $code = '';
+        if(!$user->uid) {
+            $status = 1;
+            $code = Redis::get("auth_aid:{$user->id}");
+        }
+        // 获取用户当前保存得皮肤
+        $attire = \App\Models\FittingRoom::where("account_id",$user->id)->where("curr_save", 1)->whereHas('attire', function($q){
+            $q->whereIn('cate', ['皮肤','套装']);
+        })->with(['attire'])->first();
+        //
+        //
+        $currImg1 = \Storage::disk('cosv5')->url($attire->attire->img_1);
+        $currImg2 = \Storage::disk('cosv5')->url($attire->attire->img_2);
+        //
+        $newTeach = \App\Models\Resource::where("name","new_teach")->value("src");
+        // 获取二维码的图片
+        $rqcode = \App\Models\Resource::where("name", "qr_code")->value("src");
+        //
+        $datas = \App\Models\Config::whereNotIn("key", ['box_level_percent','box_level_paster','coupon_configs'])->get(['key','val','val1','type'])->toArray();
+        foreach($datas as &$v) {
+            if($v['type'] == 1) {
+                $v['val'] = $v['val1'];   
+            }
+            unset($v['val1']);
+        }
+        //
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => [
+                'username' => $user->username,
+                'avatar' => config("filesystems.disks.cosv5.url") . '/'.$user->avatar,
+                'coupon' => $user->coupon,
+                'paster' => $user->paster,
+                'session' => $user->session,
+                'curr_attire_img1' => $currImg1,
+                'curr_attire_img2' => $currImg2,
+                'code' => $code,
+                'status' => $status,
+                "assets" => [
+                    'new_teach' => \Storage::disk('cosv5')->url($newTeach),
+                    'qr_code' => \Storage::disk('cosv5')->url($rqcode),
+                ],
+                'configs' => array_column($datas, 'val','key'),
+            ],
+        ];
+    }
+
+    // 刷新验证码
+    public function refreshCode(Request $request) {
+        //
+        $user = unserialize($request->get("account"));
+        if($user->uid) {
+            return [
+                'errno'=> 10001,
+                "errmsg" => '用户已验证,无需生成验证码',
+            ];
+        }
+        //
+        while(true) {
+            $code = mt_rand(100001,999999);
+            $tmp = Redis::get("auth_code:{$code}");
+            if(!$tmp) {
+                break;
+            }
+        }
+        //
+        Redis::set("auth_aid:{$user->id}", $code);
+        Redis::expire("auth_aid:{$user->id}", 12 * 60);
+        Redis::set("auth_code:{$code}", $user->id);
+        Redis::expire("auth_code:{$code}", 12 * 60);
+        //
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => [
+                'code' => $code,
+            ],
+        ];
+    }
+
+    // 上传分享的图片
+    public function upload(Request $request) {
+        //
+        $user = unserialize($request->get("account"));
+        //
+        $image = $request->get('img');  // your base64 encoded
+        $image = str_replace('data:image/png;base64,', '', $image);
+        $image = str_replace(' ', '+', $image);
+
+        $imagePath= 'share/'.\Str::random(10) . '.png';
+        \Storage::disk('admin')->put($imagePath, base64_decode($image));
+        //
+        // $path = $request->file("img")->store('share','admin');
+        //
+        // return \Storage::disk('admin')->download($imagePath);
+        //
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => [
+                'url' => \Storage::disk('cosv5')->url($imagePath),
+            ],
+        ];
+    }
+
+    // 客户端要用
+    public function attire(Request $request) {
+        // 
+        $uid = $request->input("uid","");
+        $token = $request->input("token","");
+        //
+        if(!$uid) {
+            return [
+                'errno'=> 10001,
+                "errmsg" => 'uid错误, 不能为空',
+            ];
+        }
+        if(!$token || $token != 'e55a4f01f5fcd56f0ddef7b078b5b2cc') {
+            return [
+                'errno'=> 10002,
+                "errmsg" => 'token错误',
+            ];
+        }
+        //
+        $account = \App\Models\Account::where("uid",$uid)->first();
+        if(!$account) {
+            return [
+                'errno'=> 10003,
+                "errmsg" => 'uid错误',
+            ];
+        }
+        // 查找用户上传的皮肤
+        $attire = \App\Models\FittingRoom::where("account_id", $account->id)
+            ->where("curr_upload",1)
+            ->with("attire")
+            ->get();
+        //
+        $ret = [];
+        foreach($attire as $v) {
+            if(isset($v['attire']) && $v['attire']) {
+                $ret[] = [
+                    'id' => $v['attire_id'],
+                    'cate' => $v['attire']['cate'],
+                    'level' => $v['attire']['level'],
+                ];
+            }
+            
+        }
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => $ret,
+        ];
+    }
+
+    // 
+    public function todo(Request $request) {
+        //
+        $user = unserialize($request->get("account"));
+        //
+        $user->uid = 1;
+        $user->save();
+        //
+        $status = 2; // 1:未验证 2:已登录
+        $code = '';
+        // 获取用户当前保存得皮肤
+        $attire = \App\Models\FittingRoom::where("account_id",$user->id)->where("curr_save", 1)->whereHas('attire', function($q){
+            $q->whereIn('cate', ['皮肤','套装']);
+        })->with(['attire'])->first();
+        //
+        //
+        $currImg1 = \Storage::disk('cosv5')->url($attire->attire->img_1);
+        $currImg2 = \Storage::disk('cosv5')->url($attire->attire->img_2);
+        //
+        $newTeach = \App\Models\Resource::where("name","new_teach")->value("src");
+        //
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => [
+                'username' => $user->username,
+                'avatar' => $user->avatar,
+                'coupon' => $user->coupon,
+                'paster' => $user->paster,
+                'session' => $user->session,
+                'curr_attire_img1' => $currImg1,
+                'curr_attire_img2' => $currImg2,
+                'code' => $code,
+                'status' => $status,
+                "assets" => [
+                    'new_teach' => \Storage::disk('cosv5')->url($newTeach),
+                ],
+            ],
+        ];
+    }
+}

+ 174 - 0
app/Http/Controllers/AuthController.php

@@ -0,0 +1,174 @@
+<?php
+
+namespace App\Http\Controllers;
+use Illuminate\Support\Facades\Redis;
+
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Http;
+
+class AuthController extends Controller
+{
+    //
+    public function login(Request $request) {
+        //
+        $code = $request->input("code","");
+        if(!$code) {
+            return [
+                'errno'=> 10001,
+                "errmsg" => '参数错误',
+            ];
+        }
+        // 调用接口可获取用户公开信息,例如头像,昵称,openid等
+        $ret = $this->thirdAuth($code);
+        if(!$ret) {
+            return [
+                'errno'=> 10002,
+                "errmsg" => '参数错误',
+            ];
+        }
+        // 通过openid判断是否存在
+        $user = \App\Models\Account::where("openid", $ret['openid'])->first();
+        $isCreate = false;
+        if(!$user) {
+            $isCreate = true;
+            $user = new \App\Models\Account();
+            $user->coupon = 0;
+            $user->paster = 0;
+            $user->uid = 0;
+            $user->code = '';
+        }
+        // $user->token = json_encode($token);
+        $user->username = $ret['name'];
+        $user->avatar = $ret['face'];
+        $user->openid = $ret['openid'];
+        //
+        $user->session = md5($user->id."_".time());
+        $user->session_expire = date("Y-m-d H:i:s", strtotime("+30 day"));
+        $user->save();
+        //
+        if($isCreate) {
+            // 把默认皮肤加入到试衣间
+            $defaultAttireId = \App\Models\Attire::where("is_default", 1)->value("id");
+            $objFittingRoom = new \App\Models\FittingRoom();
+            $objFittingRoom->account_id = $user->id;
+            $objFittingRoom->attire_id = $defaultAttireId;
+            $objFittingRoom->curr_save = 1;
+            $objFittingRoom->curr_upload = 1;
+            $objFittingRoom->save();
+        }
+        // 判断用户时候关联Uid
+        $status = 2; // 1:未验证 2:已登录
+        $code = '';
+        if(!$user->uid) {
+            $status = 1;
+            $code = Redis::get("auth_aid:{$user->id}");
+            if(!$code) {
+                while(true) {
+                    $code = mt_rand(100001,999999);
+                    $tmp = Redis::get("auth_code:{$code}");
+                    if(!$tmp) {
+                        break;
+                    }
+                }
+                //
+                Redis::set("auth_aid:{$user->id}", $code);
+                Redis::expire("auth_aid:{$user->id}", 12 * 60);
+                Redis::set("auth_code:{$code}", $user->id);
+                Redis::expire("auth_code:{$code}", 12 * 60);
+            }
+        }
+        // 获取用户当前保存的皮肤
+        $attire = \App\Models\FittingRoom::where("account_id",$user->id)->where("curr_save", 1)->whereHas('attire', function($q){
+            $q->whereIn('cate', ['皮肤','套装']);
+        })->with(['attire'])->first();
+        //
+        $currImg1 = \Storage::disk('cosv5')->url($attire->attire->img_1);
+        $currImg2 = \Storage::disk('cosv5')->url($attire->attire->img_2);
+        // 获取新手教程的图片
+        $newTeach = \App\Models\Resource::where("name","new_teach")->value("src");
+        // 获取二维码的图片
+        $rqcode = \App\Models\Resource::where("name", "qr_code")->value("src");
+        //
+        $datas = \App\Models\Config::whereNotIn("key", ['box_level_percent','box_level_paster','coupon_configs'])->get(['key','val','val1','type'])->toArray();
+        foreach($datas as &$v) {
+            if($v['type'] == 1) {
+                $v['val'] = $v['val1'];   
+            }
+            unset($v['val1']);
+        }
+        //
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => [
+                'username' => $user->username,
+                'avatar' => config("filesystems.disks.cosv5.url") . '/'.$user->avatar,
+                'coupon' => $user->coupon,
+                'paster' => $user->paster,
+                'session' => $user->session,
+                'curr_attire_img1' => $currImg1,
+                'curr_attire_img2' => $currImg2,
+                'code' => $code,
+                'status' => $status,
+                "assets" => [
+                    'new_teach' => \Storage::disk('cosv5')->url($newTeach),
+                    'qr_code' => \Storage::disk('cosv5')->url($rqcode),
+                ],
+                'configs' => array_column($datas, 'val','key'),
+            ],
+        ];
+    }
+
+    // 第三方授权获取用户基本信息
+    // https://passport.bilibili.com/register/pc_oauth2.html#/?client_id=e17f50dbe6c84974&return_url=https%3A%2F%2Fnebulabeat.com&response_type=code&state=vvvv
+    public function thirdAuth($code='') {
+        //
+        if(!$code) {
+            return false;
+        }
+        //
+        $resp = Http::timeout(3)->retry(3, 100)->post("https://api.bilibili.com/x/account-oauth2/v1/token", [
+            'client_id' => env('BCLIENTID'),
+            'client_secret' => env('BSECRET'),
+            'grant_type' => 'authorization_code',
+            'code' => $code,
+        ])->json();
+        if($resp['code'] == 0 && isset($resp['data']['access_token']) && $resp['data']['access_token']) {
+            // 获取用户信息
+            $user = Http::timeout(3)->retry(3, 100)->get("http://member.bilibili.com/arcopen/fn/user/account/info",[
+                "client_id"=>env('BCLIENTID'),
+                "access_token"=>$resp['data']['access_token'],
+            ])->json();
+            // 
+            if($user['code'] == 0 && $user['data']) {
+                // 把头像下载下来
+                $var = pathinfo($user['data']['face']);
+                $md5 = time();
+                // $tmp = $this->GrabImage($user['data']['face'], public_path("uploads/avatar/{$md5}_{$var['basename']}"));
+                $tmp = $this->GrabImage($user['data']['face'], "avatar/{$md5}_{$var['basename']}");
+                if($tmp) {
+                    $user['data']['face'] = "avatar/{$md5}_{$var['basename']}";
+                }
+                //
+                return $user['data'];
+            }
+        }
+        return false;
+    }
+    //
+    function GrabImage($url, $filename="") { 
+        if($url=="") {
+            return false;
+        }
+        //
+        ob_start(); 
+        readfile($url); 
+        $img = ob_get_contents(); 
+        ob_end_clean(); 
+        \Storage::disk("cosv5")->put($filename, $img);
+        // $fp2 = fopen($filename, "a"); 
+        // fwrite($fp2,$img); 
+        // fclose($fp2); 
+        return true; 
+    } 
+}

+ 283 - 0
app/Http/Controllers/BoxController.php

@@ -0,0 +1,283 @@
+<?php
+
+namespace App\Http\Controllers;
+use Illuminate\Support\Facades\Storage;
+use Illuminate\Support\Facades\DB;
+
+use Illuminate\Http\Request;
+
+class BoxController extends Controller
+{
+    // 获取用户信息
+    public function open(Request $request) {
+        //
+        $user = unserialize($request->get("account"));
+        // 校验参数
+        $num = $request->input("num", 1);
+        if($num !=1 && $num !=5) {
+            return [
+                'errno'=> 10001,
+                "errmsg" => '参数错误',
+            ];
+        }
+        $perCoupon = 1;
+        if($perCoupon * $num > $user->coupon) {
+            return [
+                'errno'=> 10002,
+                "errmsg" => '请求失败,礼劵不够了',
+            ];
+        }
+        // 获取基本数据
+        $levelPercent = $this->getLevelPercent();
+        $levelPaster = $this->getLevelPaster();
+        $hitCnt = $this->getBoxHit()['hit_cnt'];
+        // 循环执行
+        $result = [];
+        $ids = [];
+        $mapBoxId = [];
+        // dd($hitCnt);
+        $user_last_hit_cnt = $user->last_hit_cnt;
+        for($i=0;$i<$num;$i++) {
+            $tmp = $this->getOpenResult($user_last_hit_cnt, $levelPercent, $hitCnt);
+            if($tmp['level'] == 'SSR') {
+                $user_last_hit_cnt = 0;
+            } else {
+                $user_last_hit_cnt++;
+            }
+            $result[] = $tmp;
+            $ids[] = $tmp['attire_id'];
+            $mapBoxId[$tmp['attire_id']] = $tmp['id']; // 获取box_id 和 attire_id的映射关系
+        }
+        // 获取装扮的数据 名称/正面图片
+        $attires = \App\Models\Attire::whereIn("id", $ids)
+            ->get()
+            ->toArray();
+        $mapAttire = array_column($attires, null,"id");
+        //
+        $existAttire = \App\Models\FittingRoom::where("account_id", $user->id)
+            ->whereIn("attire_id", $ids)
+            ->pluck("attire_id")
+            ->toArray();
+        unset($ids);
+        //
+        $gainIds = [];
+        $gainAttireIds = [];
+        $retrieveIds = [];
+        $retrievePaster = 0;
+        foreach($result as &$v) {
+            $tmpAttireId = $v["attire_id"];
+            $v["name"] = $mapAttire[$tmpAttireId]["name"];
+            $v["img_1"] = Storage::disk('cosv5')->url($mapAttire[$tmpAttireId]["img_1"]);
+            //
+            if($existAttire && in_array($tmpAttireId, $existAttire)) {
+                $retrieveIds[] = $mapBoxId[$tmpAttireId];
+                $retrievePaster += (int)$levelPaster[$v["level"]];
+                $v["is_retrieve"] = 1;
+                $v["retrieve_paster"] = (int)$levelPaster[$v["level"]];
+            } else {
+                $gainIds[] = $mapBoxId[$tmpAttireId];
+                $gainAttireIds[] = $tmpAttireId;
+                $v["is_retrieve"] = 0;
+                $v["retrieve_paster"] = 0;
+                $existAttire[] = $tmpAttireId;
+            }
+        }
+        unset($v); // 解决php的引用bug
+        // 使用事务进行处理
+        DB::transaction(function () use($gainIds, $retrieveIds, $user, $perCoupon, $num, $retrievePaster, $user_last_hit_cnt,$gainAttireIds) {
+            // 更新未抽中大赏的数量
+            DB::table('accounts')
+                ->where('id', $user->id)
+                ->update(['last_hit_cnt' => $user_last_hit_cnt]);
+            // 删除花费的礼劵
+            DB::table('accounts')
+                ->where("id", $user->id)
+                ->decrement("coupon", $perCoupon * $num);
+            // 回收的贴纸数
+            if($retrievePaster) {
+                DB::table('accounts')
+                    ->where("id", $user->id)
+                    ->increment("paster", $retrievePaster);
+            }
+            // 未回收的加入试衣间
+            $fittimgRooms = [];
+            foreach($gainAttireIds as &$v) {
+                $fittimgRooms[$v] = [
+                    "account_id" => $user->id,
+                    "attire_id" => $v,
+                    'created_at' =>date("Y-m-d H:i:s"),
+                    'updated_at' =>date("Y-m-d H:i:s"),
+                ];
+            }
+            if($fittimgRooms) {
+                \App\Models\FittingRoom::insertOrIgnore(array_values($fittimgRooms));
+            }
+            // 礼盒记录
+            $objBoxRecord = new \App\Models\BoxRecord();
+            $objBoxRecord->account_id = $user->id;
+            $objBoxRecord->num = $num;
+            $objBoxRecord->box_ids = implode(",", $gainIds);
+            $objBoxRecord->retrieve_pasters = $retrievePaster;
+            $objBoxRecord->retrieve_box_ids = implode(",", $retrieveIds);
+            $objBoxRecord->cost_coupons = $perCoupon * $num;
+            $objBoxRecord->save();
+            // 礼劵明细记录
+            $objCouponRecord = new \App\Models\CouponRecord();
+            $objCouponRecord->account_id = $user->id;
+            $objCouponRecord->add_cnt = -1 * $perCoupon * $num;
+            $objCouponRecord->type = 1;
+            $objCouponRecord->box_record_id = $objBoxRecord->id;
+            $objCouponRecord->day = date("Y-m-d");
+            $objCouponRecord->save();
+            // 贴纸回收记录
+            if($retrievePaster) {
+                $objPasterRecord = new \App\Models\PasterRecord();
+                $objPasterRecord->account_id = $user->id;
+                $objPasterRecord->add_cnt = $retrievePaster;
+                $objPasterRecord->type = 1;
+                $objPasterRecord->box_record_id = $objBoxRecord->id;
+                $objPasterRecord->day = date("Y-m-d");
+                $objPasterRecord->save();
+            }
+        });
+        //
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => $result,
+        ];
+    }
+    // 一次得开礼盒计算
+    private function getOpenResult($user_last_hit_cnt, $levelPercent, $hitCnt) {
+        // 获取所有的ssr随机取一个
+        if($user_last_hit_cnt >= $hitCnt-1) {
+            $level = 'SSR';
+        } else {
+            //
+            $levels = [];
+            foreach($levelPercent as $k=>$v) {
+                for($i=0;$i<$v;$i++) {
+                    $levels[] = $k;
+                }
+            }
+            shuffle($levels);
+            $idx = array_rand($levels);
+            $level =  $levels[$idx];
+        }
+        // 随机取一个
+        $gifts = \App\Models\GiftBox::whereHas("attire", function($q) use ($level) {
+            $q->where("level", $level);
+        })->get(["id","attire_id"])->toArray();
+        //
+        foreach($gifts as &$v) {
+            $v['level'] = $level;
+        }
+        shuffle($gifts);
+        $idx = array_rand($gifts);
+        $hitGifts = $gifts[$idx];  
+        //
+        return $hitGifts;
+    }
+    //
+    public function getLevelPercent() {
+        $obj = \App\Models\Config::where("key", "box_level_percent")->first();
+        if ($obj && $obj->val) {
+            $data = json_decode($obj->val, true);
+            if ($data) {
+                return $data;
+            }
+        }
+        //
+        return config("avatar.box_level_percent");
+    }
+    //
+    public function getLevelPaster() {
+        //
+        $obj = \App\Models\Config::where("key", "box_level_paster")->first();
+        if ($obj && $obj->val) {
+            $data = json_decode($obj->val, true);
+            if ($data) {
+                return $data;
+            }
+        }
+        //
+        return config("avatar.box_level_paster");
+    }
+    //
+    public function getBoxHit() {
+        //
+        $obj = \App\Models\Config::where("key", "box_hit_cnt")->first();
+        if ($obj && $obj->val) {
+            return  ['hit_cnt'=>(int)$obj->val];
+        }
+        //
+        return config("avatar.box_hit_cnt");
+    }
+
+    // 获取礼盒装扮列表
+    public function gifts(Request $request) {
+        // 随机取一个
+        $gifts = \App\Models\GiftBox::with(["attire"])->orderBy("sort","asc")->orderBy("id","asc")->get(["attire_id"])->toArray();
+        $result = [];
+        $ret = [];
+        foreach($gifts as $v) {
+            $result[$v["attire"]["level"]][] = [
+                "name" => $v["attire"]["name"],
+                "img_1" => Storage::disk('cosv5')->url($v["attire"]["img_1"]),
+                "level" => $v["attire"]["level"],
+            ];
+            $ret[] = [
+                "name" => $v["attire"]["name"],
+                "img_1" => Storage::disk('cosv5')->url($v["attire"]["img_1"]),
+                "level" => $v["attire"]["level"],
+            ];
+        }
+        //
+        // $ret = [];
+        // $ret = array_merge($ret, $result['SSR']);
+        // $ret = array_merge($ret, $result['SR']);
+        // $ret = array_merge($ret, $result['R']);
+        // $ret = array_merge($ret, $result['N']);
+        // 获取级别的概率
+        $levelPercent = \App\Models\Config::where("key", 'box_level_percent')->value("val");
+        $levelPercent = json_decode($levelPercent, true);
+        //
+        $t = [];
+        $t['SSR'] = sprintf("%g%%", $levelPercent['SSR']);
+        $t['SR'] = sprintf("%g%%", $levelPercent['SR']);
+        $t['R'] = sprintf("%g%%", $levelPercent['R']);
+        $t['N'] = sprintf("%g%%", $levelPercent['N']);
+        $levelPercent = $t;
+        //
+        $hitCnt = \App\Models\Config::where("key", 'box_hit_cnt')->value("val");
+        $levels = [
+            [
+                'level_name' => 'SSR',
+                'percent' => $levelPercent['SSR'],
+                'relations' => $result['SSR']
+            ],
+            [
+                'level_name' => 'SR',
+                'percent' => $levelPercent['SR'],
+                'relations' => $result['SR']
+            ],
+            [
+                'level_name' => 'R',
+                'percent' => $levelPercent['R'],
+                'relations' => $result['R']
+            ],
+            [
+                'level_name' => 'N',
+                'percent' => $levelPercent['N'],
+                'relations' => $result['N']
+            ],
+        ];
+        //
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => $ret,
+            'percent_data' => compact('levelPercent','hitCnt','levels'),
+        ];
+    }
+}

+ 30 - 0
app/Http/Controllers/CommonController.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Redis;
+
+class CommonController extends Controller
+{
+    //
+    // 文案配置
+    public function configs(Request $request) {
+        //
+        $datas = \App\Models\Config::whereNotIn("key", ['box_level_percent','box_level_paster','coupon_configs'])->get(['key','val','val1','type'])->toArray();
+        foreach($datas as &$v) {
+            if($v['type'] == 1) {
+                $v['val'] = $v['val1'];   
+            }
+            unset($v['val1']);
+        }
+        //
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => array_column($datas, 'val','key'),
+        ];
+    }
+
+    
+}

+ 13 - 0
app/Http/Controllers/Controller.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
+use Illuminate\Foundation\Bus\DispatchesJobs;
+use Illuminate\Foundation\Validation\ValidatesRequests;
+use Illuminate\Routing\Controller as BaseController;
+
+class Controller extends BaseController
+{
+    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
+}

+ 43 - 0
app/Http/Controllers/CouponController.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Redis;
+
+class CouponController extends Controller
+{
+    //
+    // 礼劵配置
+    public function config(Request $request) {
+        //
+        $ret = [];
+        $obj = \App\Models\Config::where("key", "coupon_configs")->first();
+        if ($obj && $obj->val) {
+            $data = json_decode($obj->val, true);
+            if ($data) {
+                $data["img"] = \Storage::disk('cosv5')->url($data['img']);
+                $ret = $data;
+            }
+        }
+        if(!$ret) {
+            $ret = [
+                'img_title'=> '限定活动排期',
+                'img'=> '',
+                'desc_title'=> '如何获得更多礼劵?',
+                'desc'=> <<<string
+礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则
+
+礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则礼劵获取规则
+string,
+            ];
+        }
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => $ret,
+        ];
+    }
+
+    
+}

+ 121 - 0
app/Http/Controllers/FittingRoomController.php

@@ -0,0 +1,121 @@
+<?php
+
+namespace App\Http\Controllers;
+use Illuminate\Support\Facades\DB;
+
+use Illuminate\Http\Request;
+
+class FittingRoomController extends Controller
+{
+    // 试衣间装扮列表
+    public function show(Request $request) {
+        //
+        $objUser = unserialize($request->get("account"));
+        //
+        $objFittingRoom = \App\Models\FittingRoom::where("account_id", $objUser->id)->with(['attire'])->OrderByDesc("id")->get()->toArray();
+        // 按照类别进行分类
+        $result = [
+            '皮肤' => [
+                'cate' => '皮肤',
+                'relations' => [],
+            ],
+            '套装' => [
+                'cate' => '套装',
+                'relations' => [],
+            ],
+        ];
+        foreach($objFittingRoom as $v) {
+            $result[$v['attire']['cate']]['relations'][] = [
+                'attire_id' => $v['attire_id'],
+                'curr_save' => $v['curr_save'],
+                'name' => $v['attire']['name'],
+                // 'cate' => $v['attire']['cate'],
+                'img_1' => \Storage::disk('cosv5')->url($v['attire']['img_1']),
+                'img_2' => \Storage::disk('cosv5')->url($v['attire']['img_2']),
+            ];
+        }
+        $result = array_values($result);
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => $result,
+        ];
+    }
+
+    // 保存接口
+    public function save(Request $request) {
+        //
+        $objUser = unserialize($request->get("account"));
+        //
+        // dd($request->input('attire_ids'));
+        $ids = $request->input('attire_ids', []);
+        if(!$ids) {
+            return [
+                'errno'=> 10001,
+                "errmsg" => '参数错误',
+            ];
+        }
+        //
+        $arrId = DB::table("fitting_rooms")->where("account_id", $objUser->id)
+            ->whereIn("attire_id", $ids)
+            ->pluck("attire_id");
+        if(count($arrId) < count($ids)) {
+            return [
+                'errno'=> 10002,
+                "errmsg" => '参数错误',
+            ];
+        }
+        // 先把现在的保存去掉,然后上传的修改为保存
+        DB::transaction(function () use($ids, $objUser) {
+            //
+            DB::table("fitting_rooms")
+                ->where("account_id", $objUser->id)
+                ->where("curr_save",1)
+                ->update(['curr_save'=>0]);
+            //
+            DB::table("fitting_rooms")
+                ->where("account_id", $objUser->id)
+                ->whereIn("attire_id", $ids)
+                ->update(['curr_save'=>1]);
+        });
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+        ];
+
+    }
+
+    // 上传接口
+    public function upload(Request $request) {
+        //
+        $objUser = unserialize($request->get("account"));
+        // 先把现在的保存去掉,然后上传的修改为保存
+        DB::transaction(function () use($objUser) {
+            //
+            DB::table("fitting_rooms")
+                ->where("account_id", $objUser->id)
+                ->where("curr_upload",1)
+                ->update(['curr_upload'=>0]);
+            //
+            DB::table("fitting_rooms")
+                ->where("account_id", $objUser->id)
+                ->where("curr_save",1)
+                ->update(['curr_upload'=>1]);
+        });
+        // 获取分享的直播间列表
+        $resources = \App\Models\LiveRoom::where("is_show_share", 1)
+            ->orderBy("sort","asc")
+            ->orderBy("id","asc")
+            ->get(["name","img","room_id"])
+            ->toArray();
+        foreach($resources as &$v) {
+            $v['url'] = "https://live.bilibili.com/h5/{$v['room_id']}";
+            $v["img"] = \Storage::disk('cosv5')->url($v["img"]);
+        }
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            "data" => $resources,
+        ];
+    }
+}

+ 177 - 0
app/Http/Controllers/GiftController.php

@@ -0,0 +1,177 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+
+class GiftController extends Controller
+{
+    //
+    public function list(Request $request) {
+        $objUser = unserialize($request->get("account"));
+        //
+        $objGift = \App\Models\Gift::with(['attire'])->OrderBy("sort")->get()->toArray();
+        $return = [];
+        foreach($objGift as $v) {
+            // 按照自然月计算
+            if($v['type'] == 1) {
+                $cnt = \App\Models\GiftRecord::where("account_id", $objUser->id)
+                    ->where("gift_id", $v['id'])
+                    ->where("created_at",">=", date("Y-m-01 00:00:00", strtotime("first day of last month")))
+                    ->sum('num');
+            } else {
+                $cnt = \App\Models\GiftRecord::where("account_id", $objUser->id)->where("gift_id", $v['id'])->sum('num');
+            }
+            //
+            $stillCnt = $v['limit'] - $cnt;
+            if($stillCnt <= 0) {
+                $stillCnt = 0;
+            }
+            //
+            if($v['type'] == 1) {
+                $tmp = [
+                    'id' => $v['id'],
+                    'name' => '礼劵',
+                    'img' => \Storage::disk('cosv5')->url($v['img']),
+                    'cost' => $v['cost_pasters'],
+                    'info' => $v['info'],
+                    'limit' => $stillCnt,
+                ];
+            } elseif($v['type'] == 2) {
+                $tmp = [
+                    'id' => $v['id'],
+                    'name' => $v['attire']['name'],
+                    'img' => \Storage::disk('cosv5')->url($v['attire']['img_1']),
+                    'cost' => $v['cost_pasters'],
+                    'info' => $v['info'],
+                    'limit' => $stillCnt,
+                ];
+            }
+            $return[] = $tmp;
+        }
+        
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => $return,
+        ];
+    }
+
+    // 兑换接口
+    public function exchange(Request $request) {
+        $objUser = unserialize($request->get("account"));
+        //
+        $giftId = $request->input("id", 0);
+        $num = $request->input("num", 0);
+        if(!$giftId || !$num) {
+            return [
+                'errno'=> 10001,
+                "errmsg" => '参数错误',
+            ];
+        }
+        $objGift = \App\Models\Gift::where("id", $giftId)->with(['attire'])->first();
+        //
+        if(!$objGift) {
+            return [
+                'errno'=> 10002,
+                "errmsg" => '参数错误',
+            ];
+        }
+        if($objGift->limit < $num) {
+            return [
+                'errno'=> 10005,
+                "errmsg" => '参数错误',
+            ];
+        }
+        //
+        if($objGift->type == 1) {
+            $cnt = \App\Models\GiftRecord::where("account_id", $objUser->id)
+                ->where("gift_id", $giftId)
+                ->where("created_at",">=", date("Y-m-01 00:00:00", strtotime("first day of last month")))
+                ->count();
+        } else {
+            $cnt = \App\Models\GiftRecord::where("account_id", $objUser->id)->where("gift_id", $giftId)->count();
+        }
+        // $cnt = \App\Models\GiftRecord::where("account_id", $objUser->id)->where("gift_id", $giftId)->count();
+        $stillCnt = $objGift->limit - $cnt;
+        if($stillCnt <= 0) {
+            $stillCnt = 0;
+        }
+        if($num > $stillCnt) {
+            return [
+                'errno'=> 10003,
+                "errmsg" => '超出剩余限购次数('.$stillCnt.')',
+            ];
+        }
+        if($objUser->paster < $objGift->cost_pasters*$num) {
+            return [
+                'errno'=> 10004,
+                "errmsg" => '剩余贴纸数('.$objUser->paster.')不足,无法兑换',
+            ];
+        }
+        // 如果试衣间已经有了,不能进行兑换
+        if($objGift->type == 2) {
+            $tmp = \App\Models\FittingRoom::where("account_id", $objUser->id)->where("attire_id", $objGift->attire_id)->first();
+            if($tmp) {
+                return [
+                    'errno'=> 10006,
+                    "errmsg" => '已经拥有这个装扮,兑换失败',
+                ];
+            }
+        }
+        // 使用事务进行处理
+        DB::transaction(function () use($objUser, $objGift, $num) {
+            $costPaster = $objGift->cost_pasters*$num;
+            //
+            DB::table('accounts')
+                ->where('id', $objUser->id)
+                ->decrement('paster', $costPaster);
+            //
+            if($objGift->type == 1) {
+                $singleCoupon = 1;
+                DB::table('accounts')
+                ->where('id', $objUser->id)
+                ->increment('coupon', $singleCoupon*$num);
+            } elseif($objGift->type == 2) {
+                $fittimgRooms = [
+                    "account_id" => $objUser->id,
+                    "attire_id" => $objGift->attire_id,
+                    'created_at' =>date("Y-m-d H:i:s"),
+                    'updated_at' =>date("Y-m-d H:i:s"),
+                ];
+                \App\Models\FittingRoom::insertOrIgnore($fittimgRooms);
+            }
+            // 礼品记录表
+            $objGiftRecord = new \App\Models\GiftRecord();
+            $objGiftRecord->account_id = $objUser->id;
+            $objGiftRecord->gift_id = $objGift->id;
+            $objGiftRecord->num = $num;
+            $objGiftRecord->cost_paster = $costPaster;
+            $objGiftRecord->save();
+            // 贴纸明细表
+            $objPasterRecord = new \App\Models\PasterRecord();
+            $objPasterRecord->account_id = $objUser->id;
+            $objPasterRecord->add_cnt = -1*$costPaster;
+            $objPasterRecord->type = 2;
+            $objPasterRecord->gift_record_id = $objGiftRecord->id;
+            $objPasterRecord->day = date("Y-m-d");
+            $objPasterRecord->save();
+            // 礼劵明细记录
+            if($objGift->type==1) {
+                $objCouponRecord = new \App\Models\CouponRecord();
+                $objCouponRecord->account_id = $objUser->id;
+                $objCouponRecord->add_cnt = $singleCoupon*$num;
+                $objCouponRecord->type = 4;
+                $objCouponRecord->gift_record_id = $objGiftRecord->id;
+                $objCouponRecord->day = date("Y-m-d");
+                $objCouponRecord->save();
+            }
+        });
+        
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+        ];
+    }
+}

+ 121 - 0
app/Http/Controllers/GiftPackController.php

@@ -0,0 +1,121 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Redis;
+
+class GiftPackController extends Controller
+{
+    public $rooms = [
+        "14578426"=> "战斗吧",         //粉丝牌:"战姬众",
+		"23225527"=> "Nebula-Beat", //"NB人",
+		"23303212"=> "唐九夏",         //"夏韭菜",
+		"23221095"=> "吉诺儿",     //"波波派",
+		"24087754"=> "罗兹",   //罗兹Blazing
+    ];
+    //
+    // 礼包列表接口
+    public function list(Request $request) {
+        //
+        $objUser = unserialize($request->get("account"));
+        // 获取所有的礼包
+        $objPacks = \App\Models\GiftPack::with("attire")->orderBy("sort","asc")->get()->toArray();
+        // 获取用户的兑换情况
+        $objPackRecords = \App\Models\PackRecord::where("account_id", $objUser->id)->pluck("gift_pack_id")->toArray();
+        //
+        $data = [];
+        foreach($objPacks as $v) {
+            $data[] = [
+                'id' => $v['id'],
+                'name' => $v['name'],
+                'img' => \Storage::disk('cosv5')->url($v['img']),
+                'info' => '内含'.$v['coupon'].'张礼券+1个应援装扮',
+                'exchage_info' => "请前往<span style='color:#FF229F;'>".$this->rooms[$v["room_id"]]."直播间</span>,佩戴兑换礼包对应<span style='color:#FF229F;'>粉丝牌</span>,发送<span style='color:#FF229F;'>任意弹幕</span>,如账号身份满足对应兑换要求(粉丝牌1级以上),即可获得礼包。",
+                'is_exchange' => in_array($v['id'], $objPackRecords)? 1: 0,
+            ];
+        }
+        //
+        return [
+            'errno'=> 10000,
+            "errmsg" => 'ok',
+            'data' => $data,
+        ];
+    }
+
+    // 礼包兑换接口
+    public function exchange(Request $request) {
+        //
+        $objUser = unserialize($request->get("account"));
+        $id = $request->input("id", 0);
+        if(!$id) {
+            return [
+                'errno'=> 10001,
+                "errmsg" => '参数错误',
+            ];
+        }
+        // 获取礼包
+        $objPack = \App\Models\GiftPack::where("id", $id)->with("attire")->first();
+        if(!$objPack) {
+            return [
+                'errno'=> 10002,
+                "errmsg" => '参数错误',
+            ];
+        }
+        // 获取用户的兑换情况
+        $objPackRecords = \App\Models\PackRecord::where("account_id", $objUser->id)
+            ->where("gift_pack_id",$id)
+            ->first();
+        //
+        if($objPackRecords) {
+            return [
+                'errno'=> 10003,
+                "errmsg" => '该礼包已经兑换过了',
+            ];
+        }
+        // todo 用户是否直播间发送弹幕,是否符合要求  
+        if(Redis::get("dm_level:".date("Ymd").":{$objUser->id}:{$objPack->room_id}") != 1) {
+            return [
+                'errno'=> 10004,
+                "errmsg" => '还没有完成礼包任务哦',
+            ];
+        }
+        //
+        DB::transaction(function () use($objUser, $id, $objPack) {
+            // 添加兑换记录
+            $objPackRecord = new \App\Models\PackRecord();
+            $objPackRecord->account_id = $objUser->id;
+            $objPackRecord->gift_pack_id = $id;
+            $objPackRecord->save();
+            // 增加礼劵
+            DB::table('accounts')
+                ->where("id", $objUser->id)
+                ->increment("coupon", $objPack->coupon);
+            // 礼劵明细
+            $objCouponRecord = new \App\Models\CouponRecord();
+            $objCouponRecord->account_id = $objUser->id;
+            $objCouponRecord->add_cnt = $objPack->coupon;
+            $objCouponRecord->type = 5;
+            $objCouponRecord->pack_record_id = $objPackRecord->id;
+            $objCouponRecord->day = date("Y-m-d");
+            $objCouponRecord->save();
+            // 试衣间增加
+            if($objPack->attire_id) {
+                $fittimgRooms[] = [
+                    "account_id" => $objUser->id,
+                    "attire_id" => $objPack->attire_id,
+                    'created_at' =>date("Y-m-d H:i:s"),
+                    'updated_at' =>date("Y-m-d H:i:s"),
+                ];
+                \App\Models\FittingRoom::insertOrIgnore($fittimgRooms);
+            }
+        });
+        
+        //
+        return [
+            'errno'=> 10000,
+            "errmsg" => '快去试衣间装扮一下吧~',
+        ];
+    }
+}

+ 68 - 0
app/Http/Kernel.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace App\Http;
+
+use Illuminate\Foundation\Http\Kernel as HttpKernel;
+
+class Kernel extends HttpKernel
+{
+    /**
+     * The application's global HTTP middleware stack.
+     *
+     * These middleware are run during every request to your application.
+     *
+     * @var array<int, class-string|string>
+     */
+    protected $middleware = [
+        // \App\Http\Middleware\TrustHosts::class,
+        \App\Http\Middleware\TrustProxies::class,
+        \Fruitcake\Cors\HandleCors::class,
+        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
+        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
+        \App\Http\Middleware\TrimStrings::class,
+        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
+    ];
+
+    /**
+     * The application's route middleware groups.
+     *
+     * @var array<string, array<int, class-string|string>>
+     */
+    protected $middlewareGroups = [
+        'web' => [
+            \App\Http\Middleware\EncryptCookies::class,
+            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
+            \Illuminate\Session\Middleware\StartSession::class,
+            // \Illuminate\Session\Middleware\AuthenticateSession::class,
+            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
+            \App\Http\Middleware\VerifyCsrfToken::class,
+            \Illuminate\Routing\Middleware\SubstituteBindings::class,
+        ],
+
+        'api' => [
+            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
+            'throttle:api',
+            \Illuminate\Routing\Middleware\SubstituteBindings::class,
+        ],
+    ];
+
+    /**
+     * The application's route middleware.
+     *
+     * These middleware may be assigned to groups or used individually.
+     *
+     * @var array<string, class-string|string>
+     */
+    protected $routeMiddleware = [
+        'auth' => \App\Http\Middleware\Authenticate::class,
+        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
+        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
+        'can' => \Illuminate\Auth\Middleware\Authorize::class,
+        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
+        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
+        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
+        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
+        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
+        'check.auth' => \App\Http\Middleware\checkAuthMiddleware::class,
+    ];
+}

+ 21 - 0
app/Http/Middleware/Authenticate.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Auth\Middleware\Authenticate as Middleware;
+
+class Authenticate extends Middleware
+{
+    /**
+     * Get the path the user should be redirected to when they are not authenticated.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return string|null
+     */
+    protected function redirectTo($request)
+    {
+        if (! $request->expectsJson()) {
+            return route('login');
+        }
+    }
+}

+ 17 - 0
app/Http/Middleware/EncryptCookies.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
+
+class EncryptCookies extends Middleware
+{
+    /**
+     * The names of the cookies that should not be encrypted.
+     *
+     * @var array<int, string>
+     */
+    protected $except = [
+        //
+    ];
+}

+ 17 - 0
app/Http/Middleware/PreventRequestsDuringMaintenance.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
+
+class PreventRequestsDuringMaintenance extends Middleware
+{
+    /**
+     * The URIs that should be reachable while maintenance mode is enabled.
+     *
+     * @var array<int, string>
+     */
+    protected $except = [
+        //
+    ];
+}

+ 32 - 0
app/Http/Middleware/RedirectIfAuthenticated.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Providers\RouteServiceProvider;
+use Closure;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+
+class RedirectIfAuthenticated
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
+     * @param  string|null  ...$guards
+     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
+     */
+    public function handle(Request $request, Closure $next, ...$guards)
+    {
+        $guards = empty($guards) ? [null] : $guards;
+
+        foreach ($guards as $guard) {
+            if (Auth::guard($guard)->check()) {
+                return redirect(RouteServiceProvider::HOME);
+            }
+        }
+
+        return $next($request);
+    }
+}

+ 19 - 0
app/Http/Middleware/TrimStrings.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
+
+class TrimStrings extends Middleware
+{
+    /**
+     * The names of the attributes that should not be trimmed.
+     *
+     * @var array<int, string>
+     */
+    protected $except = [
+        'current_password',
+        'password',
+        'password_confirmation',
+    ];
+}

+ 20 - 0
app/Http/Middleware/TrustHosts.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Http\Middleware\TrustHosts as Middleware;
+
+class TrustHosts extends Middleware
+{
+    /**
+     * Get the host patterns that should be trusted.
+     *
+     * @return array<int, string|null>
+     */
+    public function hosts()
+    {
+        return [
+            $this->allSubdomainsOfApplicationUrl(),
+        ];
+    }
+}

+ 28 - 0
app/Http/Middleware/TrustProxies.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Http\Middleware\TrustProxies as Middleware;
+use Illuminate\Http\Request;
+
+class TrustProxies extends Middleware
+{
+    /**
+     * The trusted proxies for this application.
+     *
+     * @var array<int, string>|string|null
+     */
+    protected $proxies;
+
+    /**
+     * The headers that should be used to detect proxies.
+     *
+     * @var int
+     */
+    protected $headers =
+        Request::HEADER_X_FORWARDED_FOR |
+        Request::HEADER_X_FORWARDED_HOST |
+        Request::HEADER_X_FORWARDED_PORT |
+        Request::HEADER_X_FORWARDED_PROTO |
+        Request::HEADER_X_FORWARDED_AWS_ELB;
+}

+ 17 - 0
app/Http/Middleware/VerifyCsrfToken.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
+
+class VerifyCsrfToken extends Middleware
+{
+    /**
+     * The URIs that should be excluded from CSRF verification.
+     *
+     * @var array<int, string>
+     */
+    protected $except = [
+        //
+    ];
+}

+ 53 - 0
app/Http/Middleware/checkAuthMiddleware.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Closure;
+use Illuminate\Http\Request;
+
+class checkAuthMiddleware
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
+     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
+     */
+    public function handle(Request $request, Closure $next)
+    {
+        //
+        $session = $request->header('token','');
+        if(!$session) {
+            return response()
+            ->json([
+                'errno'=> 20000,
+                "errmsg" => '请先登录',
+            ]);
+        }
+        // 通过openid判断是否存在
+        $user = \App\Models\Account::where("session", $session)->first();
+        if(!$user) {
+            return response()
+            ->json([
+                'errno'=> 20000,
+                "errmsg" => '请先登录',
+            ]);
+        }
+        //
+        if(strtotime($user->session_expire) < time()) {
+            return response()
+            ->json([
+                'errno'=> 20000,
+                "errmsg" => '请先登录',
+            ]);
+        }
+        //
+        $user->session_expire = date("Y-m-d H:i:s", strtotime("+30 day"));
+        $user->save();
+        // $account = serialize($user);
+        $request->attributes->set('account',serialize($user));//添加参数
+        //
+        return $next($request);
+    }
+}

+ 11 - 0
app/Models/Account.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Account extends Model
+{
+	use HasDateTimeFormatter;    }

+ 19 - 0
app/Models/Attire.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Database\Eloquent\Model;
+
+class Attire extends Model
+{
+    use HasDateTimeFormatter;
+    use SoftDeletes;
+    // 礼盒
+    public function giftBox()
+    {
+        return $this->hasOne(\App\Models\GiftBox::class);
+    }
+    //
+}

+ 18 - 0
app/Models/BoxRecord.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class BoxRecord extends Model
+{
+	use HasDateTimeFormatter;
+    protected $table = 'box_records';
+    //
+    public function account()
+    {
+        return $this->belongsTo(\App\Models\Account::class);
+    }
+}

+ 11 - 0
app/Models/Config.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Config extends Model
+{
+	use HasDateTimeFormatter;    }

+ 17 - 0
app/Models/CouponRecord.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class CouponRecord extends Model
+{
+	use HasDateTimeFormatter;
+    protected $table = 'coupon_records';
+    public function account()
+    {
+        return $this->belongsTo(\App\Models\Account::class);
+    }
+}

+ 25 - 0
app/Models/FittingRoom.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class FittingRoom extends Model
+{
+	use HasDateTimeFormatter;
+    protected $table = 'fitting_rooms';
+
+    protected $guarded = ['account_id','attire_id'];
+    //
+    public function attire()
+    {
+        return $this->belongsTo(\App\Models\Attire::class)->withTrashed();
+    }
+
+    public function account()
+    {
+        return $this->belongsTo(\App\Models\Account::class);
+    }
+}

+ 17 - 0
app/Models/Gift.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Database\Eloquent\Model;
+
+class Gift extends Model
+{
+	use HasDateTimeFormatter;
+    use SoftDeletes;
+    public function attire()
+    {
+        return $this->belongsTo(\App\Models\Attire::class)->withTrashed();
+    }
+}

+ 20 - 0
app/Models/GiftBox.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Database\Eloquent\Model;
+
+class GiftBox extends Model
+{
+    use HasDateTimeFormatter;
+    use SoftDeletes;
+
+    protected $table = 'gift_boxes';
+
+    public function attire()
+    {
+        return $this->belongsTo(\App\Models\Attire::class)->withTrashed();
+    }
+}

+ 21 - 0
app/Models/GiftPack.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Database\Eloquent\Model;
+
+class GiftPack extends Model
+{
+	use HasDateTimeFormatter;
+    use SoftDeletes;
+
+    protected $table = 'gift_packs';
+
+    public function attire()
+    {
+        return $this->belongsTo(\App\Models\Attire::class)->withTrashed();
+    }
+    
+}

+ 24 - 0
app/Models/GiftRecord.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class GiftRecord extends Model
+{
+	use HasDateTimeFormatter;
+    protected $table = 'gift_records';
+
+    public function account()
+    {
+        return $this->belongsTo(\App\Models\Account::class);
+    }
+
+    public function gift()
+    {
+        return $this->belongsTo(\App\Models\Gift::class)->withTrashed();
+    }
+    
+}

+ 14 - 0
app/Models/LiveRoom.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class LiveRoom extends Model
+{
+	use HasDateTimeFormatter;
+    protected $table = 'live_rooms';
+    
+}

+ 24 - 0
app/Models/PackRecord.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class PackRecord extends Model
+{
+	use HasDateTimeFormatter;
+    protected $table = 'pack_records';
+
+    public function account()
+    {
+        return $this->belongsTo(\App\Models\Account::class);
+    }
+
+    public function giftPack()
+    {
+        return $this->belongsTo(\App\Models\GiftPack::class)->withTrashed();
+    }
+    
+}

+ 23 - 0
app/Models/PasterRecord.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class PasterRecord extends Model
+{
+	use HasDateTimeFormatter;
+    protected $table = 'paster_records';
+    //
+    public function account()
+    {
+        return $this->belongsTo(\App\Models\Account::class);
+    }
+
+    // public function gift()
+    // {
+    //     return $this->belongsTo(\App\Models\Gift::class);
+    // }
+}

+ 14 - 0
app/Models/Resource.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Resource extends Model
+{
+	use HasDateTimeFormatter;    
+    public $timestamps = false;
+
+}

Some files were not shown because too many files changed in this diff