소스 검색

代码部署

黄宗昌 2 년 전
커밋
3b4fb57f8e
100개의 변경된 파일7142개의 추가작업 그리고 0개의 파일을 삭제
  1. 18 0
      .editorconfig
  2. 62 0
      .env.example
  3. 5 0
      .gitattributes
  4. 18 0
      .gitignore
  5. 14 0
      .styleci.yml
  6. 137 0
      README.md
  7. 51 0
      app/Admin/Actions/AdminSetting.php
  8. 9 0
      app/Admin/Controllers/AuthController.php
  9. 86 0
      app/Admin/Controllers/ColumnController.php
  10. 30 0
      app/Admin/Controllers/HomeController.php
  11. 81 0
      app/Admin/Controllers/ProductController.php
  12. 119 0
      app/Admin/Controllers/ProductTypeController.php
  13. 72 0
      app/Admin/Controllers/ReportController.php
  14. 95 0
      app/Admin/Controllers/ReportLogController.php
  15. 120 0
      app/Admin/Controllers/SettingController.php
  16. 99 0
      app/Admin/Controllers/UserController.php
  17. 79 0
      app/Admin/Controllers/UserMemberController.php
  18. 106 0
      app/Admin/Controllers/UserMemberOrderController.php
  19. 96 0
      app/Admin/Forms/AdminSetting.php
  20. 100 0
      app/Admin/Metrics/Examples/NewDevices.php
  21. 155 0
      app/Admin/Metrics/Examples/NewLock.php
  22. 155 0
      app/Admin/Metrics/Examples/NewUsers.php
  23. 114 0
      app/Admin/Metrics/Examples/ProductOrders.php
  24. 117 0
      app/Admin/Metrics/Examples/Sessions.php
  25. 116 0
      app/Admin/Metrics/Examples/Tickets.php
  26. 108 0
      app/Admin/Metrics/Examples/TotalLock.php
  27. 107 0
      app/Admin/Metrics/Examples/TotalUsers.php
  28. 16 0
      app/Admin/Repositories/Column.php
  29. 16 0
      app/Admin/Repositories/Product.php
  30. 16 0
      app/Admin/Repositories/ProductType.php
  31. 16 0
      app/Admin/Repositories/Question.php
  32. 16 0
      app/Admin/Repositories/QuestionType.php
  33. 16 0
      app/Admin/Repositories/Report.php
  34. 16 0
      app/Admin/Repositories/ReportLog.php
  35. 16 0
      app/Admin/Repositories/User.php
  36. 16 0
      app/Admin/Repositories/UserMember.php
  37. 16 0
      app/Admin/Repositories/UserMemberOrder.php
  38. 32 0
      app/Admin/bootstrap.php
  39. 25 0
      app/Admin/routes.php
  40. 44 0
      app/Console/Commands/AnJuKePicker.php
  41. 243 0
      app/Console/Commands/DataSeeder.php
  42. 47 0
      app/Console/Commands/DongFangDiPicker.php
  43. 64 0
      app/Console/Commands/UserRepair.php
  44. 185 0
      app/Console/Commands/importMap.php
  45. 41 0
      app/Console/Kernel.php
  46. 45 0
      app/Exceptions/Handler.php
  47. 170 0
      app/Helper/AttachmentHelper.php
  48. 65 0
      app/Helper/JpushHelper.php
  49. 31 0
      app/Helper/LogHelper.php
  50. 196 0
      app/Helper/PayHelper.php
  51. 332 0
      app/Helper/function.php
  52. 42 0
      app/Http/Controllers/Controller.php
  53. 39 0
      app/Http/Controllers/V1/ArticleController.php
  54. 87 0
      app/Http/Controllers/V1/AttachmentController.php
  55. 313 0
      app/Http/Controllers/V1/AuthController.php
  56. 33 0
      app/Http/Controllers/V1/BaseConfigController.php
  57. 94 0
      app/Http/Controllers/V1/Controller.php
  58. 102 0
      app/Http/Controllers/V1/EmailController.php
  59. 38 0
      app/Http/Controllers/V1/IndexController.php
  60. 74 0
      app/Http/Controllers/V1/MemberController.php
  61. 436 0
      app/Http/Controllers/V1/PayController.php
  62. 264 0
      app/Http/Controllers/V1/ProductController.php
  63. 46 0
      app/Http/Controllers/V1/RegionController.php
  64. 99 0
      app/Http/Controllers/V1/SettingsController.php
  65. 64 0
      app/Http/Controllers/V1/SmsController.php
  66. 211 0
      app/Http/Controllers/V1/UserController.php
  67. 155 0
      app/Http/Controllers/V1/UserFolderController.php
  68. 67 0
      app/Http/Kernel.php
  69. 21 0
      app/Http/Middleware/Authenticate.php
  70. 17 0
      app/Http/Middleware/EncryptCookies.php
  71. 17 0
      app/Http/Middleware/PreventRequestsDuringMaintenance.php
  72. 32 0
      app/Http/Middleware/RedirectIfAuthenticated.php
  73. 19 0
      app/Http/Middleware/TrimStrings.php
  74. 20 0
      app/Http/Middleware/TrustHosts.php
  75. 23 0
      app/Http/Middleware/TrustProxies.php
  76. 17 0
      app/Http/Middleware/VerifyCsrfToken.php
  77. 95 0
      app/Models/AccountLog.php
  78. 14 0
      app/Models/Article.php
  79. 21 0
      app/Models/BaseAttachment.php
  80. 82 0
      app/Models/BaseConfig.php
  81. 28 0
      app/Models/BaseDistrict.php
  82. 22 0
      app/Models/Column.php
  83. 12 0
      app/Models/EmailCode.php
  84. 14 0
      app/Models/Help.php
  85. 11 0
      app/Models/MailCode.php
  86. 86 0
      app/Models/Order.php
  87. 32 0
      app/Models/Product.php
  88. 81 0
      app/Models/ProductType.php
  89. 11 0
      app/Models/Region.php
  90. 20 0
      app/Models/Report.php
  91. 29 0
      app/Models/ReportLog.php
  92. 65 0
      app/Models/Setting.php
  93. 15 0
      app/Models/SmsRecord.php
  94. 101 0
      app/Models/User.php
  95. 23 0
      app/Models/UserCollect.php
  96. 29 0
      app/Models/UserFolder.php
  97. 20 0
      app/Models/UserFolderImage.php
  98. 19 0
      app/Models/UserFollow.php
  99. 19 0
      app/Models/UserLike.php
  100. 14 0
      app/Models/UserMember.php

+ 18 - 0
.editorconfig

xqd
@@ -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

+ 62 - 0
.env.example

xqd
@@ -0,0 +1,62 @@
+APP_NAME=Laravel
+APP_ENV=local
+APP_KEY=base64:JCvirjK+4zF8Z6X9vkk2xFvMFT0cK2r1D159ycsThiw=
+APP_DEBUG=true
+APP_URL=http://localhost
+ADMIN_HTTPS=false
+
+LOG_CHANNEL=stack
+LOG_LEVEL=debug
+
+DB_CONNECTION=mysql
+DB_HOST=127.0.0.1
+DB_PORT=3306
+DB_DATABASE=demo
+DB_USERNAME=root
+DB_PASSWORD=root123
+
+BROADCAST_DRIVER=log
+CACHE_DRIVER=file
+FILESYSTEM_DRIVER=local
+QUEUE_CONNECTION=sync
+SESSION_DRIVER=file
+SESSION_LIFETIME=120
+
+#Dingo API
+API_STANDARDS_TREE=prs
+API_SUBTYPE=api
+API_PREFIX=api
+API_VERSION=v1
+API_DEBUG=true
+
+
+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}"
+
+JWT_SECRET=vIdNecn1HtbC5fmQ5I4V8R0GWMK7KQPEwnJBgJgKpIqDvsYDSLYycUrfPXdFqppk

+ 5 - 0
.gitattributes

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

+ 18 - 0
.gitignore

xqd
@@ -0,0 +1,18 @@
+/node_modules
+/public/hot
+/public/storage
+/public/upload
+/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
+.DS_Store
+/public/uploads

+ 14 - 0
.styleci.yml

xqd
@@ -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

+ 137 - 0
README.md

xqd
@@ -0,0 +1,137 @@
+
+### 项目概要
+该项目为  思维定制基础API标准 
+
+接口文档https://console-docs.apipost.cn/preview/ec5add2de84f3f15/7f7e45104ec643f0
+
+技术说明 https://docs.qq.com/doc/DVUxlS1FrWVJYcmtG 
+
+```
+
+## 技术架构
+
+* PHP >8.0.0
+* MySQL >5.6.0
+* Nginx >1.12.0
+* Laravel 8.x (8.0)
+* PHP扩展安装fileinfo, redis, 删除禁用函数 putenv,proc_open
+##安装
+1. git clone 到本地
+2. 执行 composer install (导入sql创建好数据库)
+3. 配置 .env 中数据库连接信息,没有.env请复制.env.example命名为.env
+4. 执行 php artisan key:generate
+执行 php artisan migrate (可忽略)
+执行 php artisan db:seed (可忽略)
+
+## Dcat-Admin 资源发布
+```
+$ php artisan admin:publish
+$ php artisan admin:install
+```
+
+
+## 创建 JWT secret
+```
+$ php artisan jwt:secret
+
+```
+
+## 安装第三方组件
+
+>注意:可以自定义 [`composer`](https://mirrors.aliyun.com/composer/) 镜像,加快拉取速度
+
+```
+composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
+
+```
+
+## 短信
+$result = SmsService::send($request->mobile, $request->event, [], $user);
+## 邮箱
+1. Mail::raw($notice, function ($message) use ($email) {
+2. $message->subject(trans('api.MAILBOX_VALIDATION_NOTIFICATION'));
+    $message->to($email);
+3. 邮箱配置
+   MAIL_MAILER=smtp
+   MAIL_HOST=ssl://smtp.163.com
+   MAIL_PORT=465
+   MAIL_USERNAME=youxiang@163.com
+   MAIL_PASSWORD=VIBTDHQAYLKJYIGC
+   MAIL_ENCRYPTION=
+   MAIL_FROM_ADDRESS=youxiang@163.com
+   MAIL_FROM_NAME="${APP_NAME}"
+});
+## 文件上传
+$api->post('attachment/upload', ['uses' => 'AttachmentController@upload',]);
+
+### 创建目录
+
+> 注意:git clone 从仓库拉取的代码,可能会存在 storage 目录缺失的问题,需要手动创建
+
+```
+$ mkdir -p storage/{app,debugbar,framework,logs}
+$ mkdir -p storage/framework/{cache,sessions,testing,views}
+
+```
+
+```
+$ chmod -R 777 storage bootstrap/cache
+```
+
+## 创建 storage 到 public 的软链接
+
+> 注意:如果是 Docker 环境,此步骤必须在容器内执行
+
+```
+$ php artisan storage:link
+```
+
+### 数据迁移
+
+> 注意:如果是 Docker 环境,此步骤必须在容器内执行
+> 注意:原始SQL 迁移文件不在本项目
+
+```
+$ php artisan migrate
+```
+
+## 其它第三方包 PHP 扩展包视频教程 https://learnku.com/courses/laravel-package/2019
+
+# Dcat-admin-packages 开源扩展包列表
+
+- [changzhong/extension-iframe-tabs](https://github.com/changzhong/extension-iframe-tabs) dcat-admin iframe多窗口扩展
+- [celaraze/mellita](https://github.com/IronnMan/mellita) Mellita 可以使任何 Laravel 应用具备 SaaS 能力,只需要简单的 composer 安装以及极其少量的改动。无论你是打算使用 Laravel 项目开发新项目,还是将已经付出努力的项目转化为 SaaS 架构,都可以轻松实现。
+- [deatil/dcat-login-captcha](https://github.com/deatil/dcat-login-captcha) Dcat-admin 登陆验证码
+- [guanguans/dcat-login-captcha](https://github.com/guanguans/dcat-login-captcha) Dcat-admin 登录验证码
+- [deatil/dcat-form-media](https://github.com/deatil/dcat-form-media) Dcat-admin 表单媒体拓展
+- [jqhph/dcat-admin-ueditor](https://github.com/jqhph/dcat-admin-ueditor) Ueditor是一个Dcat Admin的扩展包,集成百度在线编辑器,支持附件上传等功能。
+- [celaraze/dcat-extension-plus](https://github.com/celaraze/dcat-extension-plus) 为 DcatAdmin 后台添加增强配置的功能。修改过程利用 DcatAdmin 自带的 admin_setting() 方法实现,不会硬编码修改任何 config 文件或者 .env 文件。
+- [super-eggs/dcat-distpicker](https://github.com/super-eggs/dcat-distpicker) Distpicker是一个中国省市区三级联动选择组件,这个包是基于 Distpicker 的 dcat-admin 扩展,用来将 Distpicker 集成进 dcat-admin的表单中。
+- [lty5240/dcat-easy-sku](https://github.com/lty5240/dcat-easy-sku) 基于Dcat Admin的Sku插件
+- [Abbotton/dcat-admin-setting-extension](https://github.com/Abbotton/dcat-admin-setting-extension) Dcat Admin系统配置插件
+- [dcat-admin/form-step](https://github.com/dcat-admin/form-step) Dcat Admin 分步表单扩展
+- [mosiboom/dcat-iframe-tab](https://github.com/mosiboom/dcat-iframe-tab) 这个扩展包基于laravel框架和dcat-admin框架,为解决dcat-admin没有自带兼容iframe架构。使用此扩展包可以构建出一个iframe架构并带有标签页管理的后台框架。
+- [tanmotop/dcat-admin-permission-plus](https://github.com/tanmotop/dcat-admin-permission-plus) dcat-admin extension permission-plus
+- [ArrowJustDoIt/dcat-admin-crontab-extension](https://github.com/ArrowJustDoIt/dcat-admin-crontab-extension) Crontab是一个dcat-admin后台的定时任务扩展插件,你可以通过此插件定时执行shell、sql以及访问指定链接
+- [Lichmaker/ladder-admin](https://github.com/Lichmaker/ladder-admin) 基于dcat-admin编写的v2ray管理后台
+- [dcat-admin/operation-log](https://github.com/dcat-admin/operation-log) Dcat Admin 操作日志扩展
+- [Sparkinzy/dcat-kindeditor](https://github.com/Sparkinzy/dcat-kindeditor) dcat-admin扩展kindeditor5.0.1
+- [asundust/dcat-auth-captcha](https://github.com/asundust/dcat-auth-captcha) dcat-admin登陆 滑动验证插件 多平台支持
+- [jyiL/log-viewer](https://github.com/jyiL/log-viewer) 错误日志查看
+- [nealwon/dcat-admin-echarts](https://github.com/nealwon/dcat-admin-echarts) dcat admin echarts extension
+- [nivin-studio/dcat-ext-taskscheduling](https://github.com/nivin-studio/dcat-ext-taskscheduling) 一个Dcat Admin的定时任务可视化管理的插件
+- [Death-Satan/dcat-env](https://github.com/Death-Satan/dcat-env) Dcat Admin Extension edit env file
+- [puzzle9/dact-admin-wang-editor](https://github.com/puzzle9/dact-admin-wang-editor) Dcat Admin扩展 - WangEditor
+- [dairidong/dcat-media-manager](https://github.com/dairidong/dcat-media-manager) Dcat Admin的文件管理扩展(源于 Laravel Admin 的相同扩展)
+- [TyrantG/dcat-admin-braft-editor](https://github.com/TyrantG/dcat-admin-braft-editor) Dcat Admin扩展 - Braft Editor编辑器
+- [dcat-phper/dcat-extension-gallery](https://gitee.com/dcat-phper/dcat-extension-gallery) dcat-admin 预览图片扩展,支持多图,放大、缩小、旋转等
+- [slowlyo/dcat-amis](https://gitee.com/slowlyo/dcat-amis) Dcat Admin 的 amis组件扩展, 可以在 dcat 中轻松使用 amis 组件, 让你开发自定义页面变得更简单
+- [sparkinzy/dcat-distpicker](https://github.com/Sparkinzy/dcat-distpicker) Distpicker 是一个中国省市区三级联动选择组件
+- [sparkinzy/dcat-extension-client](https://github.com/Sparkinzy/dcat-extension-client) Dcat Admin 非官方应用市场,让扩展不再难找
+
+# Dcat-admin 应用
+- [nxcrm](https://github.com/shebaoting/nxcrm) 基于laravel的客户管理系统(CRM)
+- [laravel-box](https://gitee.com/dcat-phper/laravel-box) 整合laravel、dcat-admin、jwt、iseed、easy-wechat 、laravel-debugbar 等后台应用的开发包。管理后台开发所需的都在这里,省去配置步骤,开箱即用。
+- [chemex](https://github.com/celaraze/chemex) 咖啡壶是一个免费、开源、高效且漂亮的运维资产管理平台。
+- [Discover](https://github.com/youyingxiang/Discover) Discover 是一个基于 Dcat-admin 开发的进销存系统
+- [saas-skeleton](https://github.com/Abbotton/saas-skeleton) 基于 Laravel & Dcat Admin 构建的 SAAS 后台脚手架

+ 51 - 0
app/Admin/Actions/AdminSetting.php

xqd
@@ -0,0 +1,51 @@
+<?php
+
+namespace App\Admin\Actions;
+
+use App\Admin\Forms\AdminSetting as AdminSettingForm;
+use Dcat\Admin\Actions\Action;
+use Dcat\Admin\Widgets\Modal;
+
+class AdminSetting extends Action
+{
+    /**
+     * @return string
+     */
+	protected $title;
+
+	public function __construct($title = null)
+    {
+        parent::__construct($title);
+        $lang = request()->session()->get('admin.config.lang');
+        switch ($lang){
+//            case 'en':// 英文
+//                $lang = 'en';
+//                break;
+            case 'ko':// 韩语
+                $lang = 'ko';
+                break;
+            default:// 中文
+                $lang = 'zh';
+                break;
+        }
+        $this->title = '<i class="feather icon-edit" style="font-size: 1.5rem"></i> '.trans('site-setting.language_settings',[],$lang);
+    }
+
+    public function render()
+    {
+        $modal = Modal::make()
+            ->id('admin-setting-config') // 导航栏显示弹窗,必须固定ID,随机ID会在刷新后失败
+            ->title($this->title())
+            ->body(AdminSettingForm::make())
+            ->lg()
+            ->button(
+                <<<HTML
+<ul class="nav navbar-nav">
+     <li class="nav-item"> &nbsp;{$this->title()}</li>
+</ul>
+HTML
+            );
+
+        return $modal->render();
+    }
+}

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

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

+ 86 - 0
app/Admin/Controllers/ColumnController.php

xqd
@@ -0,0 +1,86 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\Column;
+use App\Models\ProductType;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class ColumnController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new Column(), function (Grid $grid) {
+            $grid->column('id')->sortable();
+            $grid->column('product_type_id')->display(function (){
+                $lang = request()->session()->get('admin.config.lang');
+                if ($lang == 'ko'){
+                    $data = ProductType::query()->whereIn('id',$this->product_type_id)->pluck('ko_name')->toArray();
+                }else{
+                    $data = ProductType::query()->whereIn('id',$this->product_type_id)->pluck('zh_name')->toArray();
+                }
+                return $data;
+            })->label();
+            $grid->column('zh_name');
+            $grid->column('ko_name');
+            $grid->column('sort');
+            $grid->column('status')->switch();
+            $grid->column('created_at');
+            $grid->column('updated_at')->sortable();
+
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->equal('id');
+
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new Column(), function (Show $show) {
+            $show->field('id');
+            $show->field('product_type_id');
+            $show->field('zh_name');
+            $show->field('ko_name');
+            $show->field('sort');
+            $show->field('status');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new Column(), function (Form $form) {
+            $form->display('id')->width(4);
+            $form->multipleSelect('product_type_id')->options(ProductType::selectOptions())->required();
+            $form->text('zh_name')->required()->width(4);
+            $form->text('ko_name')->required()->width(4);
+            $form->number('sort')->width(4);
+            $form->switch('status')->default(1);
+
+            $form->display('created_at');
+            $form->display('updated_at');
+        });
+    }
+}

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

xqd
@@ -0,0 +1,30 @@
+<?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(trans('admin-home.Data_panel'))
+            ->description('')
+            ->body(function (Row $row) {
+                $row->column(10, function (Column $column) {
+                    $column->row(new Examples\NewUsers());
+                });
+                $row->column(2, function (Column $column) {
+                    $column->row(function (Row $row) {
+                        $row->column(12, new Examples\TotalUsers());
+                    });
+                });
+            });
+    }
+}

+ 81 - 0
app/Admin/Controllers/ProductController.php

xqd
@@ -0,0 +1,81 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\Product;
+use App\Admin\Repositories\ProductType;
+use App\Models\User;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class ProductController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new Product(), function (Grid $grid) {
+            $grid->model()->with(['type:id,zh_name,ko_name','user:id,name'])->orderByDesc('id');
+            $grid->column('id')->sortable();
+            $grid->column('image')->image('',40);
+            $grid->column('type.zh_name',admin_trans_field('type'));
+            $grid->column('user.name',admin_trans_field('user_id'));
+            $grid->column('name');
+            $grid->column('content');
+            $grid->column('status')->switch();
+            $grid->column('created_at');
+            $grid->disableCreateButton();
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->panel();
+                $filter->like('name')->width(3);
+                $filter->equal('type')->select(\App\Models\ProductType::selectOptions())->width(3);
+
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new Product(), function (Show $show) {
+            $show->field('id');
+            $show->field('type');
+            $show->field('user_id');
+            $show->field('name');
+            $show->field('content');
+            $show->field('image');
+            $show->field('status');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new Product(), function (Form $form) {
+            $form->display('id')->width(4);
+            $form->select('type')->options(\App\Models\ProductType::selectOptions())->required()->width(4);
+            $form->select('user_id')->width(4)->options(User::query()->where('status',1)->pluck('name','id'))->required();
+            $form->text('name')->required()->width(4);
+            $form->textarea('content')->required()->width(4);
+            $form->image('image')->autoUpload()->uniqueName()->required()->width(4);
+            $form->switch('status')->default(1);
+        });
+    }
+}

+ 119 - 0
app/Admin/Controllers/ProductTypeController.php

xqd
@@ -0,0 +1,119 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use App\Models\ProductType;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class ProductTypeController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new ProductType(), function (Grid $grid) {
+            $grid->model()->orderByDesc('sort');
+            $grid->column('id')->bold()->sortable();
+            $grid->column('icon')->image('',40);
+            $lang = request()->session()->get('admin.config.lang');
+            if ($lang == 'ko'){
+                $grid->ko_name->tree(); // 开启树状表格功能
+            }else{
+                $grid->zh_name->tree(); // 开启树状表格功能
+            }
+            $grid->column('is_upload_display')->switch();
+            $grid->column('is_filter_display')->switch();
+            $grid->column('sort');
+            $grid->column('status')->switch();
+            $grid->column('created_at');
+
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->panel();
+                $filter->like('name',admin_trans_field('name'))->width(4);
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new ProductType(), function (Show $show) {
+            $show->field('id');
+            $show->field('pid');
+            $show->field('name');
+            $show->field('sort');
+            $show->field('status');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new ProductType(), function (Form $form) {
+            $form->display('id')->width(4);
+            $form->image('icon')->autoUpload()->uniqueName()->width(4);
+            $form->select('pid')->options(ProductType::selectOptions())->required()->width(4);
+            $form->text('zh_name')->width(4)->required();
+            $form->text('ko_name')->width(4)->required();
+            $form->text('zh_alias')->width(4);
+            $form->text('ko_alias')->width(4);
+            $form->textarea('describe')->width(4);
+            $form->number('sort');
+            $form->switch('status')->default(1);
+            $form->hidden('route_id');
+            $form->hidden('filter_display_pid');
+            $form->hidden('upload_display_pid');
+            $form->hidden('is_filter_display')->default(1);
+            $form->hidden('is_upload_display')->default(1);
+
+            $form->saving(function (Form $form) {
+                if ($form->isEditing()) {
+                    if($form->is_filter_display == 0){ // 特殊筛选
+                        $id = $form->getKey();
+                        $ProductType = ProductType::query()->where('id',$id)->first();
+                        ProductType::query()->where('pid','=',$id)
+                            ->update(['filter_display_pid'=>$ProductType->pid]);
+                    }elseif ($form->is_filter_display == 1){
+                        $id = $form->getKey();
+                        ProductType::query()->where('pid','=',$id)->update(['filter_display_pid'=>null]);
+                    }
+                    if($form->is_upload_display == 0){ // 特殊上传
+                        $id = $form->getKey();
+                        $ProductType = ProductType::query()->where('id',$id)->first();
+                        ProductType::query()->where('pid','=',$id)
+                            ->update(['upload_display_pid'=>$ProductType->pid]);
+                    }elseif ($form->is_upload_display == 1){
+                        $id = $form->getKey();
+                        ProductType::query()->where('pid','=',$id)
+                            ->update(['upload_display_pid'=>null]);
+                    }
+                    if(!empty($form->pid)){
+                        $form->level = count(ProductType::level($form->pid)) + 1; // 加一级
+                        $form->route_id = implode(',',ProductType::level($form->pid)); // 加一级
+                    }else{
+                        $form->level = 1; // 加一级
+                        $form->route_id = 0;
+                    }
+                }
+            });
+        });
+    }
+}

+ 72 - 0
app/Admin/Controllers/ReportController.php

xqd
@@ -0,0 +1,72 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\Report;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class ReportController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new Report(), function (Grid $grid) {
+            $grid->column('id')->sortable();
+            $grid->column('title');
+            $grid->column('content');
+            $grid->column('sort');
+            $grid->column('status')->switch();
+            $grid->column('created_at');
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->panel();
+                $filter->like('title')->width(4);
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new Report(), function (Show $show) {
+            $show->field('id');
+            $show->field('title');
+            $show->field('content');
+            $show->field('sort');
+            $show->field('status');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new Report(), function (Form $form) {
+            $form->display('id')->width(4);
+            $form->text('title')->width(4);
+            $form->textarea('content')->width(4);
+            $form->number('sort')->width(4);
+            $form->switch('status')->default(1);
+
+            $form->display('created_at');
+            $form->display('updated_at');
+        });
+    }
+}

+ 95 - 0
app/Admin/Controllers/ReportLogController.php

xqd
@@ -0,0 +1,95 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\ReportLog;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class ReportLogController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new ReportLog(), function (Grid $grid) {
+            $grid->model()->with(['user:id,name,avatar,company_name','product:id,name,image','report:id,title']);
+            $grid->column('id')->sortable();
+            $grid->column('user_id')->display(function (){
+                $str = "";
+                if(!empty($this->user)){
+                    $str .= "<div style='margin-right:10px;display: flex;align-items: center'>";
+                    $str .= '<img data-action="preview-img" src="' . $this->user->avatar . '" style="height:50px;width:50px;cursor:pointer;margin-right:10px;" class="img img-thumbnail">';
+                    $str .= '<div>';
+                    $str .= '<p style="margin-bottom: 5px">' . $this->user->name . '</p>';
+                    $str .= "</div>";
+                    $str .= "</div>";
+                }
+                return $str;
+            });
+            $grid->column('product_id')->display(function (){
+                $str = "";
+                if(!empty($this->product)){
+                    $str .= "<div style='margin-right:10px;display: flex;align-items: center'>";
+                    $str .= '<img data-action="preview-img" src="' . $this->product->image . '" style="height:50px;width:50px;cursor:pointer;margin-right:10px;" class="img img-thumbnail">';
+                    $str .= '<div>';
+                    $str .= '<p style="margin-bottom: 5px">' . $this->product->name . '</p>';
+                    $str .= "</div>";
+                    $str .= "</div>";
+                }
+                return $str;
+            });
+            $grid->column('report_id')->display(function (){
+                return $this->report->title;
+            });
+            $grid->column('created_at');
+            $grid->disableCreateButton();
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->panel();
+                $filter->like('id')->width(4);
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new ReportLog(), function (Show $show) {
+            $show->field('id');
+            $show->field('user_id');
+            $show->field('product_id');
+            $show->field('report_id');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new ReportLog(), function (Form $form) {
+            $form->display('id');
+            $form->text('user_id');
+            $form->text('product_id');
+            $form->text('report_id');
+
+            $form->display('created_at');
+            $form->display('updated_at');
+        });
+    }
+}

+ 120 - 0
app/Admin/Controllers/SettingController.php

xqd
@@ -0,0 +1,120 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Models\AdminLog;
+use App\Models\Setting;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Http\Controllers\AdminController;
+use Dcat\Admin\Form\NestedForm;
+
+class SettingController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        request()->session()->put('current_url', url()->current()); //这段代码切换语言用的,因为 url()->previous()不生效
+        return Grid::make(new Setting(), function (Grid $grid) {
+            $grid->model()->orderBy('id');
+            $grid->model()->where('is_delete', '=','0');
+            $grid->column('id')->sortable();
+            $grid->column('title');
+            $grid->column('ko_title');
+            $grid->column('key');
+            $grid->value(admin_trans_label('setting'))->display(function () {
+                $url = admin_url('/setting/'.$this->id.'/edit');
+                $html  = '<div style="text-align:left">';
+                $html .= '<a href="'.$url.'" class="btn btn-sm btn-primary"><i class="fa fa-edit"></i>'.admin_trans_label('setting').'</a>';
+                $html .= '</div>';
+                return $html;
+            });
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->panel();
+                $filter->like('title')->width(4);
+            });
+            $grid->disableBatchDelete();
+            $grid->disableActions();
+            $grid->disableCreateButton();
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     * 注意 Setting 模型中 public function getValueAttribute($value){ return json_decode($value, true); }
+     */
+    protected function form()
+    {
+        request()->session()->put('current_url', url()->current()); //这段代码切换语言用的,因为 url()->previous()不生效
+        return Form::make(new Setting(), function (Form $form) {
+            $key = $form->model()->key;
+            $form->display('id')->width(4);
+            $form->display('title', admin_trans_field('title'));
+            $form->display('ko_title', admin_trans_field('ko_title'));
+            switch ($key){
+                case 'notice': //公告
+                        $form->editor('value.zh_content', admin_trans_field('zh'));
+                        $form->editor('value.ko_content', admin_trans_field('ko'));
+                    break;
+                case 'user_agreement': // 用户协议
+                        // 中文
+                        $form->editor('value.zh_content', admin_trans_field('zh'));
+                        // 韩文
+                        $form->editor('value.ko_content', admin_trans_field('ko'));
+                    break;
+                case 'privacy_policy': // 隐私政策
+                    // 中文
+                    $form->editor('value.zh_content', admin_trans_field('zh'));
+                    // 韩文
+                    $form->editor('value.ko_content', admin_trans_field('ko'));
+                    break;
+                case 'collection_checklist': // 收集清单
+                    // 中文
+                    $form->editor('value.zh_content', admin_trans_field('zh'));
+                    // 英文
+                    $form->editor('value.en_content', admin_trans_field('en'));
+                    break;
+                case 'shared_inventory': // 共享清单
+                    // 中文
+                    $form->editor('value.zh_content', admin_trans_field('zh'));
+                    // 英文
+                    $form->editor('value.en_content', admin_trans_field('en'));
+                    break;
+                case 'permission_description': // 权限说明
+                    // 中文
+                    $form->editor('value.zh_content', admin_trans_field('zh'));
+                    // 英文
+                    $form->editor('value.en_content', admin_trans_field('en'));
+                    break;
+                case 'customer_service': // 客服
+                        // 手机号
+                        $form->mobile('value.mobile',admin_trans_field('mobile'));
+                        // 邮箱
+                        $form->email('value.email',admin_trans_field('email'))->width(4);
+                    break;
+                case 'applet': // 小程序设置
+                    // 点钞小程序
+                    $form->switch('value.is_counting',admin_trans_field('is_counting'));
+                    // 收银小程序
+                    $form->switch('value.is_cashier',admin_trans_field('is_cashier'));
+                    break;
+                case 'version': // 版本号
+                    $form->image('value.logo',admin_trans_field('logo'))->autoUpload()->uniqueName()->width(4);
+                    $form->text('value.version',admin_trans_field('version'))->width(4);
+                    $form->file('value.file',admin_trans_field('file'))->autoUpload()->uniqueName()->width(4);
+                    break;
+            }
+            $form->saved(function (Form $form) use ($key){
+                return $form->response()->success(admin_trans_field('save_success'))->redirect('setting/'.$form->model()->id.'/edit');
+            });
+            $form->disableViewButton();
+            $form->disableDeleteButton();
+        });
+    }
+}

+ 99 - 0
app/Admin/Controllers/UserController.php

xqd
@@ -0,0 +1,99 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\User;
+use App\Models\UserLock;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class UserController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new User(), function (Grid $grid) {
+            $grid->model()->with('member:id,title');
+            $grid->column('id')->sortable();
+            $grid->column('name');
+            $grid->column('account');
+            $grid->column('email');
+            $grid->column('online')->using(config('map.online'))->label(['gray', 'success']);
+            $grid->column('member.title',admin_trans_field('member_type'))->label(['gray', 'success']);
+            $grid->column('status')->switch();
+            $grid->column('created_at')->sortable();
+            $grid->disableCreateButton();
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->panel();
+                $filter->like('name', admin_trans_field('name'))->width(4);
+                $filter->like('mobile', admin_trans_field('mobile'))->width(4);
+                $filter->like('email', admin_trans_field('email'))->width(4);
+                $filter->between('created_at', admin_trans_field('created_at'))->datetime()->width(4);
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new User(), function (Show $show) {
+            $show->field('id')->width(4);
+            $show->field('name')->width(4);
+            $show->field('email')->width(4);
+            $show->field('mobile')->width(4);
+            $show->field('jpush_reg_id')->width(4);
+            $show->field('last_login_ip')->width(4);
+            $show->field('last_login_time')->width(4);
+            $show->field('register_ip')->width(4);
+            $show->field('created_at')->width(4);
+            $show->field('updated_at')->width(4);
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new User(), function (Form $form) {
+            $form->display('id')->width(4);
+            $form->text('name')->required()->width(4);
+            $form->text('account')->required()->width(4);
+            $form->email('email')->required()->width(4);
+            $form->password('password')->default('')
+                ->placeholder('不修改时,默认为空。')
+                ->minLength(6)
+                ->maxLength(20)
+                ->customFormat(function ($v) {
+                    if ($v == $this->password) {
+                        return;
+                    }
+                    return $v;
+                })->width(4);
+            $form->switch('status')->width(4);
+            $form->display('created_at')->width(4);
+            $form->display('updated_at')->width(4);
+
+            $form->saving(function (Form $form) {
+                if(!$form->input('password')){
+                    $form->deleteInput('password');
+                }
+            });
+
+        });
+    }
+}

+ 79 - 0
app/Admin/Controllers/UserMemberController.php

xqd
@@ -0,0 +1,79 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\UserMember;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class UserMemberController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new UserMember(), function (Grid $grid) {
+            $grid->column('id')->sortable();
+            $grid->column('title');
+            $grid->column('describe');
+            $grid->column('updated_at')->sortable();
+            $grid->disableFilter();
+            $grid->disableCreateButton();
+            $grid->disableViewButton();
+            // 禁用删除按钮
+            $grid->disableDeleteButton();
+            $grid->disableBatchDelete();
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                $actions->disableDelete();
+                $actions->disableQuickEdit();
+                $actions->disableView();
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new UserMember(), function (Show $show) {
+            $show->field('id');
+            $show->field('title');
+            $show->field('describe');
+            $show->field('money');
+            $show->field('content');
+            $show->field('created_at');
+            $show->field('updated_at');
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new UserMember(), function (Form $form) {
+            $id = $form->getKey();
+            $form->display('id')->width(4);
+            $form->text('title')->width(4);
+            $form->text('describe')->width(4);
+            if($id == 2){
+                $form->decimal('money')->width(4);
+            }
+            $form->editor('content')->width(4);
+            $form->disableViewButton();
+            $form->disableDeleteButton();
+        });
+    }
+}

+ 106 - 0
app/Admin/Controllers/UserMemberOrderController.php

xqd
@@ -0,0 +1,106 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Repositories\UserMemberOrder;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+
+class UserMemberOrderController extends AdminController
+{
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new UserMemberOrder(), function (Grid $grid) {
+            $grid->model()->with('user:id,name,company_name,avatar');
+            $grid->column('id')->sortable();
+            $grid->column('user_id')->display(function (){
+                $str = '';
+                if(!empty($this->user)){
+                    $str .= '<div>';
+                    $str .= '<p style="margin-bottom: 5px">'. admin_trans('user.fields.name').':' . $this->user->name . '</p>';
+                    $str .= '<p style="margin-bottom: 5px">' . admin_trans('user.fields.company_name').':' . $this->user->company_name . '</p>';
+                    $str .= "</div>";
+                }
+                return $str;
+            });
+            $grid->column('pay_type')->display(function (){
+                return $this->pay_type_text;
+            })->label();
+            $grid->column('days');
+            $grid->column('money');
+            $grid->column('status')->display(function (){
+                return $this->status_text;
+            })->label(['gray', 'success']);
+            $grid->column('created_at');
+            $grid->disableCreateButton();
+            // 禁用删除按钮
+            // 也可以通过以下方式启用或禁用按钮
+            $grid->disableDeleteButton();
+            $grid->disableEditButton();
+            $grid->disableQuickEditButton();
+            $grid->disableViewButton();
+            $grid->disableActions();
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->panel();
+                $filter->equal('id')->width(4);
+
+            });
+        });
+    }
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new UserMemberOrder(), function (Show $show) {
+            $show->model()->with('user:id,name,company_name,avatar');
+            $show->field('id')->width(4);
+            $show->field('user_id')->width(4)->unescape()->as(function (){
+                $str = '';
+                if(!empty($this->user)){
+                    $str .= '<div>';
+                    $str .= '<p style="margin-bottom: 5px">'. admin_trans('user.fields.name').':' . $this->user->name . '</p>';
+                    $str .= '<p style="margin-bottom: 5px">' . admin_trans('user.fields.company_name').':' . $this->user->company_name . '</p>';
+                    $str .= "</div>";
+                }
+                return $str;
+            });
+            $show->field('pay_type_text',admin_trans_field('pay_type'))->width(4);
+            $show->field('status_text',admin_trans_field('status'))->width(4);
+            $show->field('days')->width(4);
+            $show->field('money')->width(4);
+            $show->field('created_at')->width(4);
+        });
+    }
+
+    /**
+     * Make a form builder.
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new UserMemberOrder(), function (Form $form) {
+            $form->display('id');
+            $form->text('user_id');
+            $form->text('pay_type');
+            $form->text('status');
+            $form->number('days');
+
+            $form->display('created_at');
+            $form->display('updated_at');
+        });
+    }
+}

+ 96 - 0
app/Admin/Forms/AdminSetting.php

xqd
@@ -0,0 +1,96 @@
+<?php
+
+namespace App\Admin\Forms;
+
+use Dcat\Admin\Contracts\LazyRenderable;
+use Dcat\Admin\Traits\LazyWidget;
+use Dcat\Admin\Widgets\Form;
+use Illuminate\Support\Arr;
+
+class AdminSetting extends Form implements LazyRenderable
+{
+    use LazyWidget;
+
+    /**
+     * 主题颜色.
+     *
+     * @var array
+     */
+    protected $colors;
+
+    public function __construct($data = [], $key = null)
+    {
+        parent::__construct($data, $key);
+        $this->colors = [
+            'default'    => trans('site-setting.Dark_blue'),
+            'blue'       => trans('site-setting.blue'),
+//          'blue-light' => '浅蓝',
+//          'blue-dark'  => '深蓝',
+            'green'      => trans('site-setting.green'),
+        ];
+    }
+
+    /**
+     * 处理表单请求.
+     *
+     * @param array $input
+     *
+     * @return mixed
+     */
+    public function handle(array $input)
+    {
+        foreach (Arr::dot($input) as $k => $v) {
+            $this->update($k, $v);
+        }
+
+        return $this->response()->success(trans('site-setting.Set_successfully'));
+    }
+
+    /**
+     * 构建表单.
+     */
+    public function form()
+    {
+        // 'en' => 'English',
+        $this->radio('lang', trans('site-setting.language'))->width(6)->required()->options(['zh' => '简体中文','ko'=>'한국어']);
+    }
+
+    /**
+     * 设置接口保存成功后的回调JS代码.
+     *
+     * 1.2秒后刷新整个页面.
+     *
+     * @return string|void
+     */
+    public function savedScript()
+    {
+        return <<<'JS'
+    if (data.status) {
+        setTimeout(function () {
+          location.reload()
+        }, 1000);
+    }
+JS;
+    }
+
+    /**
+     * 返回表单数据.
+     *
+     * @return array
+     */
+    public function default()
+    {
+        return user_admin_config();
+    }
+
+    /**
+     * 更新配置.
+     *
+     * @param string $key
+     * @param string $value
+     */
+    protected function update($key, $value)
+    {
+        user_admin_config([$key => $value]);
+    }
+}

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

xqd
@@ -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
+        );
+    }
+}

+ 155 - 0
app/Admin/Metrics/Examples/NewLock.php

xqd
@@ -0,0 +1,155 @@
+<?php
+
+namespace App\Admin\Metrics\Examples;
+
+use App\Models\User;
+use App\Models\UserLock;
+use Carbon\Carbon;
+use Dcat\Admin\Widgets\Metrics\Line;
+use Illuminate\Http\Request;
+class NewLock extends Line
+{
+    /**
+     * 初始化卡片内容
+     *
+     * @return void
+     */
+    protected function init()
+    {
+        parent::init();
+
+        $this->title(admin_trans('admin-home.New_Lock'));
+        $this->dropdown([
+            '7' => admin_trans('admin-home.Last_7_days'),
+            '30' => admin_trans('admin-home.Last_month'),
+//            '180' => admin_trans('admin-home.Last_half_year'),
+//            '365' => admin_trans('admin-home.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':
+                $user = $this->new_lock("365");
+                // 卡片内容
+                $this->withContent($user['num']);
+                // 图表数据
+                $this->withChart($user['num_arr']);
+                break;
+            case '30':
+                $user = $this->new_lock("30");
+                // 卡片内容
+                $this->withContent($user['num']);
+                // 图表数据
+                $this->withChart($user['num_arr']);
+                break;
+            case '180':
+                $user = $this->new_lock("180");
+                // 卡片内容
+                $this->withContent($user['num']);
+                // 图表数据
+                $this->withChart($user['num_arr']);
+                break;
+            case '7':
+            default:
+            $user = $this->new_lock("7");
+            // 卡片内容
+            $this->withContent($user['num']);
+            // 图表数据
+            $this->withChart($user['num_arr']);
+            break;
+        }
+    }
+
+    /**
+     *  新用户 一年
+     *   write by wanglas
+     */
+    public function new_lock($kind){
+
+        if ($kind=='365'){
+            $t_last = date('Y-m-d H:i:s',strtotime('-1 year'));
+            $t_time = 86400*12;
+            $count = 13;
+        }elseif ($kind=='180'){
+            $t_last = date('Y-m-d H:i:s',strtotime('-180 day'));
+            $t_time = 86400*6;
+            $count = 31;
+        }elseif ($kind=='30'){
+            $t_last = date('Y-m-d H:i:s',strtotime('-30 day'));
+            $t_time = 86400;
+            $count = 31;
+        }elseif ($kind=='7'){
+            $t_last = date('Y-m-d H:i:s',strtotime('-7 day'));
+            $t_time = 86400;
+            $count = 8;
+        }
+        //统计会员总数
+        $t_now = date('Y-m-d H:i:s');
+        $num = UserLock::query()->whereBetween('created_at',array($t_last,$t_now))->count();
+        //计算会员增长数量
+        for ($i=1 ; $i < $count; $i++) {
+            $today = strtotime(date('Ymd'));
+            $start_time = date('Y-m-d 23:59:59',$today-$t_time*$i);
+            $end_time  = date('Y-m-d 23:59:59',$today-$t_time*($i-1));
+            $inc_num = UserLock::query()->whereBetween('created_at',[$start_time,$end_time])->count();
+            $arr_n[]=$inc_num;
+        }
+        //逆序输出数组
+        //$arr_t=array_reverse($arr_t);  //时间
+        $arr_n=array_reverse($arr_n);  //数量
+        return array('num'=>$num,'num_arr'=>$arr_n);
+    }
+
+    /**
+     * 设置图表数据.
+     *
+     * @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
+        );
+    }
+}

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

xqd
@@ -0,0 +1,155 @@
+<?php
+
+namespace App\Admin\Metrics\Examples;
+
+use App\Models\User;
+use Dcat\Admin\Widgets\Metrics\Line;
+use Illuminate\Http\Request;
+
+class NewUsers extends Line
+{
+    /**
+     * 初始化卡片内容
+     *
+     * @return void
+     */
+    protected function init()
+    {
+        parent::init();
+
+        $this->title(admin_trans('admin-home.New_Users'));
+        $this->dropdown([
+            '7' => admin_trans('admin-home.Last_7_days'),
+            '30' => admin_trans('admin-home.Last_month'),
+//            '180' => admin_trans('admin-home.Last_half_year'),
+//            '365' => admin_trans('admin-home.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':
+                $user = $this->new_user("365");
+                // 卡片内容
+                $this->withContent($user['num']);
+                // 图表数据
+                $this->withChart($user['num_arr']);
+                break;
+            case '30':
+                $user = $this->new_user("30");
+                // 卡片内容
+                $this->withContent($user['num']);
+                // 图表数据
+                $this->withChart($user['num_arr']);
+                break;
+            case '180':
+                $user = $this->new_user("180");
+                // 卡片内容
+                $this->withContent($user['num']);
+                // 图表数据
+                $this->withChart($user['num_arr']);
+                break;
+            case '7':
+            default:
+            $user = $this->new_user("7");
+            // 卡片内容
+            $this->withContent($user['num']);
+            // 图表数据
+            $this->withChart($user['num_arr']);
+            break;
+        }
+    }
+
+    /**
+     *  新用户 一年
+     *   write by wanglas
+     */
+    public function new_user($kind){
+
+        if ($kind=='365'){
+            $t_last = date('Y-m-d H:i:s',strtotime('-1 year'));
+            $t_time = 86400*12;
+            $count = 31;
+        }elseif ($kind=='180'){
+            $t_last = date('Y-m-d H:i:s',strtotime('-180 day'));
+            $t_time = 86400*6;
+            $count = 31;
+        }elseif ($kind=='30'){
+            $t_last = date('Y-m-d H:i:s',strtotime('-30 day'));
+            $t_time = 86400;
+            $count = 30;
+        }elseif ($kind=='7'){
+            $t_last = date('Y-m-d H:i:s',strtotime('-7 day'));
+            $t_time = 86400;
+            $count = 8;
+        }
+        //统计会员总数
+        $t_now = date('Y-m-d H:i:s');
+        $num=User::query()->whereBetween('created_at',array($t_last,$t_now))->whereNull('deleted_at')->count();
+        //计算会员增长数量
+        for ($i=1 ; $i < $count; $i++) {
+            $today=strtotime(date('Ymd'));
+            $start_time = date('Y-m-d 23:59:59',$today-$t_time*$i);
+            $end_time  = date('Y-m-d 23:59:59',$today-$t_time*($i-1));
+            $inc_num=User::query()->whereBetween('created_at',[$start_time,$end_time])->count();
+            //$arr_t[]=$now;
+            $arr_n[]=$inc_num;
+        }
+        //逆序输出数组
+        //$arr_t=array_reverse($arr_t);  //时间
+        $arr_n=array_reverse($arr_n);  //数量
+        return array('num'=>$num,'num_arr'=>$arr_n);
+    }
+
+    /**
+     * 设置图表数据.
+     *
+     * @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

xqd
@@ -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

xqd
@@ -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

xqd
@@ -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
+        );
+    }
+}

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

xqd
@@ -0,0 +1,108 @@
+<?php
+
+namespace App\Admin\Metrics\Examples;
+
+use App\Models\Game;
+use App\Models\Team;
+use App\Models\User;
+use App\Models\UserLock;
+use Dcat\Admin\Widgets\Metrics\Card;
+use Illuminate\Contracts\Support\Renderable;
+use Illuminate\Http\Request;
+
+class TotalLock extends Card
+{
+    /**
+     * 卡片底部内容.
+     *
+     * @var string|Renderable|\Closure
+     */
+    protected $footer;
+
+    /**
+     * 初始化卡片.
+     */
+    protected function init()
+    {
+        parent::init();
+        $this->title(trans('admin-home.Total_Lock'));
+    }
+
+    /**
+     * 处理请求.
+     *
+     * @param Request $request
+     *
+     * @return void
+     */
+    public function handle(Request $request)
+    {
+        $total_team = UserLock::query()->count();
+        $this->content($total_team);
+    }
+
+    /**
+     * @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;cursor: pointer" onclick="location.href='/admin/user_lock'">
+    <h2 class="ml-1 font-lg-1" style="font-size: 48px!important;">{$content}</h2>
+</div>
+
+HTML;
+    }
+
+    /**
+     * 渲染卡片底部内容.
+     *
+     * @return string
+     */
+    public function renderFooter()
+    {
+        return $this->toString($this->footer);
+    }
+}

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

xqd
@@ -0,0 +1,107 @@
+<?php
+
+namespace App\Admin\Metrics\Examples;
+
+use App\Models\Game;
+use App\Models\Team;
+use App\Models\User;
+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(trans('admin-home.Total_users'));
+    }
+
+    /**
+     * 处理请求.
+     *
+     * @param Request $request
+     *
+     * @return void
+     */
+    public function handle(Request $request)
+    {
+        $total_team = User::query()->whereNull('deleted_at')->count();
+        $this->content($total_team);
+    }
+
+    /**
+     * @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;cursor: pointer" onclick="location.href='/admin/user'">
+    <h2 class="ml-1 font-lg-1" style="font-size: 48px!important;">{$content}</h2>
+</div>
+
+HTML;
+    }
+
+    /**
+     * 渲染卡片底部内容.
+     *
+     * @return string
+     */
+    public function renderFooter()
+    {
+        return $this->toString($this->footer);
+    }
+}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 32 - 0
app/Admin/bootstrap.php

xqd
@@ -0,0 +1,32 @@
+<?php
+
+use Dcat\Admin\Layout\Navbar;
+use Dcat\Admin\Admin;
+
+/**
+ * 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');
+ *
+ */
+config(['admin' => user_admin_config()]);
+config(['app.locale' => config('admin.lang') ?: config('app.locale')]);
+Admin::navbar(function (Navbar $navbar) {
+    $method = config('admin.layout.horizontal_menu') ? 'left' : 'right';
+    // ajax请求不执行
+    if (! Dcat\Admin\Support\Helper::isAjaxRequest()) {
+        $navbar->$method(App\Admin\Actions\AdminSetting::make()->render());
+    }
+});

+ 25 - 0
app/Admin/routes.php

xqd
@@ -0,0 +1,25 @@
+<?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->get('/', 'HomeController@index');
+    $router->resource('/user', 'UserController'); //用户管理
+    $router->resource('/member', 'UserMemberController'); //会员类型
+    $router->resource('/user_member_order', 'UserMemberOrderController'); //续费订单
+    $router->resource('/product', 'ProductController'); //产品列表
+    $router->resource('/product_type', 'ProductTypeController'); //产品类型
+    $router->resource('/column', 'ColumnController'); //栏目
+    $router->resource('/report', 'ReportController'); //举报问题
+    $router->resource('/report_log', 'ReportLogController'); //举报记录
+    $router->resource('/setting', 'SettingController'); //系统设置
+});

+ 44 - 0
app/Console/Commands/AnJuKePicker.php

xqd
@@ -0,0 +1,44 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+
+class AnJuKePicker extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'picker:anjuke';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Command description';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return mixed
+     */
+    public function handle()
+    {
+        //
+        $picker = new \App\Http\Controllers\Service\AnJuKePicker();
+        $picker->startPick();
+    }
+}

+ 243 - 0
app/Console/Commands/DataSeeder.php

xqd
@@ -0,0 +1,243 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Model\AccountInfo;
+use App\Model\Appeals;
+use App\Model\BaseArea;
+use App\Model\WithdrawInfo;
+use App\Model\DeliverInfo;
+use App\Model\DeviceInfo;
+use App\Model\DeviceToUser;
+use App\Model\RechargeInfo;
+use App\Model\TransportInfo;
+use App\Model\UserInfo;
+use Faker\Generator;
+use Illuminate\Console\Command;
+
+/**
+ * 数据填充器
+ * Class DataSeeder
+ * @package App\Console\Commands
+ */
+
+class DataSeeder extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'data:seeder';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Command description';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return mixed
+     */
+    public function handle()
+    {
+        //用户表数据填充300条
+
+
+
+        $faker_zh = \Faker\Factory::create('zh_CN');
+        $faker_en = \Faker\Factory::create();
+
+
+
+
+
+
+
+        $cities = BaseArea::where('pid','510117')->with(['communities'=>function($query){
+            $query->select(['area_id','id']);
+        }])->get(['id'])->toArray();
+        $area_ids = [];
+        $communities_ids =[];
+        $city_max = 0;
+        $com_max = 0;
+         foreach ($cities as $city){
+             $area_ids[]= $city['id'];
+             $city_max ++;
+             foreach ($city['communities'] as $community){
+                 $communities_ids[] = $community['id'];
+                 $com_max++;
+             }
+
+        }
+
+
+
+
+
+
+
+
+            $us = UserInfo::all(['id','role'])->toArray();
+            $user_common = [];
+            $user_agent = [];
+            $user_agent_user = [];
+            foreach ($us as $u){
+                if ($u['role'] == UserInfo::Role_Common)
+                    $user_common[] = $u['id'];
+                if ($u['role'] == UserInfo::Role_Agent)
+                    $user_agent[] = $u['id'];
+                if ($u['role'] == UserInfo::Role_Agent_User)
+                    $user_agent_user[] = $u['id'];
+            }
+
+            $us = DeviceInfo::all(['id'])->toArray();
+
+            $device_ids =[];
+            $device_max = 0;
+            foreach ($us as $u){
+                $device_max ++;
+                $device_ids[] = $u['id'];
+            }
+
+
+        for ($i = 0;$i<2000;$i++){
+            echo "第{$i}个投放记录开始创建\r\n";
+            $tempRow = [];
+            $tempRow['device_id'] = $device_ids[rand(0,$device_max-1)];
+            $tempRow['user_id'] = $user_common[rand(0,count($user_common)-1)];
+            $tempRow['no'] = strtoupper(uniqid());
+            $tempRow['weight'] = rand(1,99999);
+            $tempRow['money'] = rand(0,1000);
+            $tempRow['finished_at'] = date('Y-m-d H:i:s');
+            $tempRow['status'] = rand(1,3);
+            $tempRow['created_at'] = date('Y-m-d H:i:s',strtotime("-".rand(1,365)." days"));
+            DeliverInfo::create($tempRow);
+        }
+
+
+
+
+
+        for ($i = 0;$i<2000;$i++){
+            echo "第{$i}个收运记录开始创建\r\n";
+            $tempRow = [];
+            $tempRow['device_id'] = $device_ids[rand(0,$device_max-1)];
+            $tempRow['user_id'] = $user_agent_user[rand(0,count($user_agent_user)-1)];
+            $tempRow['no'] = strtoupper(uniqid());
+            $tempRow['weight'] = rand(1,999999);
+            $tempRow['money'] = rand(0,1000);
+            $tempRow['created_at'] = date('Y-m-d H:i:s',strtotime("-".rand(1,365)." days"));
+            $tempRow['status'] = rand(1,2);
+            TransportInfo::create($tempRow);
+        }
+
+        $banks = array(
+            '渤海银行',
+            '广发银行',
+            '国家开发银行',
+            '恒丰银行',
+            '华夏银行',
+            '交通银行',
+            '平安银行',
+            '上海浦东发展银行',
+            '兴业银行',
+            '招商银行',
+            '浙商银行',
+            '中国工商银行',
+            '中国光大银行',
+            '中国建设银行',
+            '中国民生银行',
+            '中国农业银行',
+            '中国银行',
+            '中国邮政储蓄银行',
+            '中信银行',
+        );
+
+
+        for ($i = 0;$i<2000;$i++){
+            echo "第{$i}个提现记录开始创建\r\n";
+            $tempRow = [];
+            $tempRow['user_id'] = $user_common[rand(0,count($user_common)-1)];
+            $tempRow['order_no'] = strtoupper(uniqid());
+            $tempRow['money'] = rand(0,3000);
+            $tempRow['poundage'] = rand(0,200);
+            $tempRow['pay_money'] = $tempRow['money']-$tempRow['poundage'];
+            $tempRow['paid_at'] = date('Y-m-d H:i:s');
+            $tempRow['bank_card'] = $faker_zh->phoneNumber;
+            $tempRow['bank_name'] = $banks[rand(0,count($banks)-1)];
+            $tempRow['name'] = $faker_zh->name;
+            $tempRow['mobile'] = $faker_zh->phoneNumber;
+            $tempRow['ali_account'] = $faker_zh->phoneNumber;
+            $tempRow['ali_name'] = $faker_zh->name;
+            $tempRow['status'] = rand(0,1);
+            $tempRow['type'] = rand(0,2);
+            $tempRow['created_at'] = date('Y-m-d H:i:s',strtotime("-".rand(1,365)." days"));
+            $tempRow['reason'] = $faker_en->company;
+            WithdrawInfo::create($tempRow);
+        }
+
+        for ($i = 0;$i<2000;$i++){
+            echo "第{$i}个充值记录开始创建\r\n";
+            $tempRow = [];
+            $tempRow['user_id'] =  $user_common[rand(0,count($user_common)-1)];
+            $tempRow['order_no'] = strtoupper(uniqid());
+            $tempRow['money'] = rand(0,1000);
+            $tempRow['type'] =rand(0,1);
+            $tempRow['created_at'] = date('Y-m-d H:i:s',strtotime("-".rand(1,365)." days"));
+
+            $tempRow['finished_at'] = date('Y-m-d H:i:s',strtotime("-".rand(1,365)." days"));
+            $tempRow['status'] = rand(0,1);
+            RechargeInfo::create($tempRow);
+        }
+
+
+
+        for ($i = 0;$i<2000;$i++){
+            echo "第{$i}个余额记录开始创建\r\n";
+            $tempRow = [];
+            $tempRow['user_id'] =  $user_common[rand(0,count($user_common)-1)];
+            $tempRow['method'] = rand(1,6);
+            $s = [-1,1];
+            $tempRow['admin_id'] = $s[rand(0,1)];
+            $tempRow['balance'] = rand(10,1000);
+            $tempRow['money'] =rand(10,1000);
+            $tempRow['detail'] = $faker_en->text;
+
+            AccountInfo::create($tempRow);
+        }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    }
+}

+ 47 - 0
app/Console/Commands/DongFangDiPicker.php

xqd
@@ -0,0 +1,47 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+
+class DongFangDiPicker extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'picker:dfd';
+
+    /**
+     * 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 mixed
+     */
+    public function handle()
+    {
+        //
+        $dfd = new \App\Http\Controllers\Service\DongFangDiPicker();
+        $dfd->startPick();
+
+
+
+    }
+}

+ 64 - 0
app/Console/Commands/UserRepair.php

xqd
@@ -0,0 +1,64 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Model\AccountInfo;
+use App\Model\DeliverInfo;
+use App\Model\RechargeInfo;
+use App\Model\UserInfo;
+use Illuminate\Console\Command;
+
+class UserRepair extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'user:reset';
+
+    /**
+     * 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 mixed
+     */
+    public function handle()
+    {
+        //TODO 10465 宣传员展示不删除
+        $ids = [9997,10025,10318,10340,10024,10572,10517,10690,10538,10533,10044,10679,10347,10142,10190,10329,11036,11460,10004,10045,10446,12000,12031];
+        foreach ($ids as $id){
+            $user = UserInfo::where(['id'=>$id])->first();
+            if(empty($user)){continue;}
+            $user_arr = [];
+            //echo '用户id:'.$id.'  角色'.$user->role.PHP_EOL;
+            if(!in_array($user->role,$user_arr)){
+                $user_arr[] = $user->role;
+            }
+            DeliverInfo::where(['user_id'=>$id])->delete();
+            AccountInfo::where(['user_id'=>$id])->delete();
+            RechargeInfo::where(['user_id'=>$id])->delete();
+            $data['account']=0;
+            if($user->role == 2){
+                $data['agent_account'] = 0;
+            }
+            UserInfo::where(['id'=>$id])->update($data);
+        }
+    }
+}

+ 185 - 0
app/Console/Commands/importMap.php

xqd
@@ -0,0 +1,185 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Model\BaseArea;
+use App\Model\BaseAreaNew;
+use Faker\Provider\Base;
+use Illuminate\Console\Command;
+use Overtrue\Pinyin\Pinyin;
+
+class importMap extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'import:map';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Command description';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return mixed
+     */
+    public function handle()
+    {
+    //    $data = json_decode(file_get_contents(public_path('docs/maps.txt')),true);
+
+        $total = [];
+
+//        foreach ($data['plist']['dict']['key'] as $value){
+//            $prefix = substr($value,0,6);
+//            $name = str_replace($prefix,'',$value);
+//            $total[substr($prefix,0,2)] = ['pid'=>$prefix,'name'=>$name];
+//        }
+//
+//
+//
+//
+//
+//
+//     foreach ($data['plist']['dict']['dict'] as $datum){
+//             foreach ($datum['key'] as $vv){
+//                     $g2_prefix = substr($vv,0,6);
+//                     $g2_prefix_half = substr($vv,0,2);
+//                     $name = str_replace($g2_prefix,'',$vv);
+//                     $total[substr($g2_prefix,0,4)] = ['pid'=>$g2_prefix,'name'=>$name];
+//         }
+//     }
+//
+//
+//        foreach ($data['plist']['dict']['dict'] as $datum){
+//            foreach ($datum['array'] as $vv){
+//                foreach ($vv['string'] as $vvv){
+//
+//                    $g2_prefix = substr($vvv,0,6);
+//                    $g2_prefix_half = substr($vvv,0,2);
+//                    $g2_prefix_3 = substr($vvv,0,4);
+//                    $name = str_replace($g2_prefix,'',$vvv);
+//                    $total[substr($g2_prefix,0,5)] = ['pid'=>$g2_prefix,'name'=>$name];
+//
+//                }
+//            }
+//        }
+//
+//
+//
+//
+//
+//
+//
+//        $res = BaseAreaNew::find($g2_prefix);
+//        if ($res)
+//            continue;
+//        $id = BaseAreaNew::insert([
+//            'name'=>$name,
+//            'pid'=>$total[$g2_prefix_3]['pid'],
+//            'id'=>$g2_prefix,
+//            'short_name'=>$name,
+//            'grade'=>3,
+//            'city_code'=>0,
+//            'zip_code'=>0,
+//            'merger_name'=>$total[$g2_prefix_half]['name'].','.$total[$g2_prefix_3]['name'].','.$name,
+//            'lng'=>0,
+//            'lat'=>0,
+//            'pinyin'=>'',
+//        ]);
+//
+//
+//     $dd = scandir(public_path('docs/town'));
+//
+//     $arr = array_map(function ($v){
+//         return str_replace('.json','',$v);
+//     },$dd);
+//     unset($dd);
+//     $ds = BaseAreaNew::whereIn('id',$arr)->get(['id','name','merger_name']);
+//
+//
+//     foreach ($ds as $d){
+//         $dds = json_decode(file_get_contents(public_path('docs/town/'.$d->id.'.json')),true);
+//         foreach ($dds as $k =>$v){
+//
+//             $res = BaseAreaNew::find($k);
+//        if ($res)
+//            continue;
+//        $id = BaseAreaNew::insert([
+//            'name'=>$v,
+//            'pid'=>$d->id,
+//            'id'=>$k,
+//            'short_name'=>$v,
+//            'grade'=>4,
+//            'city_code'=>0,
+//            'zip_code'=>0,
+//            'merger_name'=>$d->merger_name.','.$v,
+//            'lng'=>0,
+//            'lat'=>0,
+//            'pinyin'=>'',
+//        ]);
+//
+//        echo "{$v}:{$k} ³É¹¦µ¼ÈëÁË£¡\r\n";
+//
+//         }
+
+
+        $i = 0;
+        $maps =  BaseArea::where('relation','')->get(['pid','id']);
+
+        foreach ($maps as $map) {
+            $i++;
+            echo "Deal:{$i}\r\n";
+            $relation = ["1"];
+            $pid = $map->pid;
+            if ($pid == 1)
+                $map->update(['relation' => implode(',',$relation)]);
+
+            $relation[] = $map->id;
+            while ($pid!=1){
+                $area = BaseArea::find($pid);
+                if ($area){
+                    $relation[] = $pid;
+                    $pid = $area->pid;
+                }
+            }
+            $str = implode(',',$relation);
+
+            $map->update(['relation' => $str]);
+            echo "{$str}\r\n";
+
+
+
+
+        }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    }
+}

+ 41 - 0
app/Console/Kernel.php

xqd
@@ -0,0 +1,41 @@
+<?php
+
+namespace App\Console;
+
+use Illuminate\Console\Scheduling\Schedule;
+use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
+
+class Kernel extends ConsoleKernel
+{
+    /**
+     * The Artisan commands provided by your application.
+     *
+     * @var array
+     */
+    protected $commands = [
+        //
+    ];
+
+    /**
+     * 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');
+    }
+}

+ 45 - 0
app/Exceptions/Handler.php

xqd
@@ -0,0 +1,45 @@
+<?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
+     */
+    protected $dontReport = [
+        //
+    ];
+
+    /**
+     * A list of the inputs that are never flashed for validation exceptions.
+     *
+     * @var array
+     */
+    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) {
+            //
+        });
+    }
+
+
+
+
+}

+ 170 - 0
app/Helper/AttachmentHelper.php

xqd
@@ -0,0 +1,170 @@
+<?php
+
+namespace App\Helper;
+
+use App\Models\SystemConfig;
+use FFMpeg;
+use Illuminate\Http\Request;
+use Illuminate\Http\UploadedFile;
+use Illuminate\Support\Facades\Storage;
+use OSS\OssClient;
+use PHPUnit\Util\Exception;
+use Symfony\Component\HttpFoundation\File\Exception\FileException;
+use App\Services\Base\ErrorCode;
+use App\Models\BaseAttachment;
+
+trait AttachmentHelper
+{
+
+    public function __construct()
+    {
+        //在 .env 文件里配置下面可测试文件上传OSS
+        //ALI_OSS_ACCESS_ID=LTAI5tHMYxyoEkmGqQZjbpmk
+        //ALI_OSS_ACCESS_KEY=Fqj8J1JH0yyRpLvOjNFj5usjvfvHns
+        //ALI_OSS_BUCKET=zhengda
+        //ALI_OSS_ENDPOINT=oss-cn-chengdu.aliyuncs.com
+
+        $this->fileDriver = env('FILESYSTEM_DRIVER');
+        $this->bucket = env('ALI_OSS_BUCKET');
+        $this->accessId = env('ALI_OSS_ACCESS_ID');
+        $this->accessKey = env('ALI_OSS_ACCESS_KEY');
+        $this->endPoint = env('ALI_OSS_ENDPOINT');
+        $this->ossClient = new OssClient($this->accessId, $this->accessKey, $this->endPoint);
+    }
+
+    /**
+     * @param Request $request
+     * @param $key
+     * @param string $tag
+     * @param float|int $size
+     * @param array $mimeType
+     * @return array|mixed
+     * @throws \Exception
+     */
+    public function uploadAttachment(Request $request, $key, $tag = 'files', $size = 200 * 1024 * 1024, array $mimeType = [])
+    {
+        if ($request->hasFile($key)) {
+            $files = $request->file($key);
+            if ($files === null) {
+                throw new \Exception(trans('api.ATTACHMENT_FILE_NULL'));
+            }
+            if ($files instanceof UploadedFile) {
+                $files = [$files];
+            }
+            $result = [];
+            foreach ($files as $idx => $file) {
+                if (!$file->isValid()) {
+                    throw new \Exception(trans('api.ATTACHMENT_TYPE_ERROR'));
+                    continue;
+                }
+                $fileSize = $file->getSize();
+                if ($fileSize > $size) {
+                    throw new \Exception(trans('api.ATTACHMENT_SIZE_EXCEEDED'));
+                    continue;
+                }
+                $fileMimeType = $file->getMimeType();
+                if (!empty($mimeType) && !in_array($fileMimeType, $mimeType)) {
+                    throw new \Exception(trans('api.ATTACHMENT_TYPE_ERROR'));
+                    continue;
+                }
+                $clientName = $file->getClientOriginalName();
+                $md5 = md5($clientName . time());
+                $md5_filename = $md5 . '.' . $file->getClientOriginalExtension();
+                try {
+                    //本地上传
+                    if (env('FILESYSTEM_DRIVER') == 'local') {
+                        $rel_path = '/upload/' . $tag . '/' . date('Ymd');
+                        $path = public_path() . $rel_path;
+                        if (!file_exists($path)) {
+                            if (!@mkdir($path, 0755, true)) {
+                                throw new \Exception(trans('api.ATTACHMENT_MAKE_FOLDER_ERROR'));
+                            }
+                        }
+                        $file->move($path, $md5_filename);
+                        $realPath = $path . '/' . $md5_filename;
+                        $urlPath = $rel_path . '/' . $md5_filename;
+                        if ($fileMimeType == "video/mp4" || $fileMimeType == "video/quicktime") {
+                            $ffmpeg = FFMpeg\FFMpeg::create(array(
+                                'ffmpeg.binaries' => '/usr/bin/ffmpeg',
+                                'ffprobe.binaries' => '/usr/bin/ffprobe'
+                            ));
+                            $video = $ffmpeg->open($realPath);
+                            $vpath = public_path() . '/upload/vpic/';
+                            if (!file_exists($vpath)) {
+                                if (!@mkdir($vpath, 0755, true)) {
+                                    return trans('api.ATTACHMENT_MAKE_FOLDER_ERROR');
+                                }
+                            }
+                            $pic = $vpath . $md5 . '.jpg';
+                            $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(1))->save($pic);
+                        }
+                        $result[$idx] = 'http://' . $_SERVER['HTTP_HOST'] . $urlPath;
+
+                    } elseif (env('FILESYSTEM_DRIVER') == 'oss') {
+
+                        $tmppath  = $file->getRealPath(); //获取上传图片的临时地址
+                        $fileName = date('YmdHis') .rand(10000, 99999). '.' . $file->getClientOriginalExtension(); //生成文件名
+                        $pathName = $tag . '/' . date('Y-m') . '/' . $fileName;
+                        $upResult = $this->ossClient->uploadFile($this->bucket, $pathName, $tmppath, ['ContentType' => $file->getClientMimeType()]); //上传图片到阿里云OSS
+                        $url = $upResult['info']['url'];
+                        $realPath = $url;
+                        $urlPath  = $url;
+                        $result[$idx] = $url;
+                    }
+                    //将上传的图片存入到数据表作为记录
+                    $attachment = new BaseAttachment();
+                    $attachment->name = $clientName;
+                    $attachment->md5  = $md5;
+                    $attachment->path = $realPath;
+                    $attachment->url  = $urlPath;
+                    $attachment->size = $fileSize;
+                    $attachment->file_type = $fileMimeType;
+                    if (!$attachment->save()) {
+                        @unlink($realPath);
+                        throw new \Exception(trans('api.ATTACHMENT_SAVE_ERROR'));
+                    }
+                } catch (FileException $e) {
+                    throw new \Exception(trans('api.ATTACHMENT_UPLOAD_INVALID'));
+                }
+            }
+            if (count($result) == 1) {
+                return array_shift($result);
+            }
+            return $result;
+        } else {
+            throw new \Exception(trans('api.ATTACHMENT_UPLOAD_INVALID'));
+        }
+    }
+
+    /**
+     * 删除附件
+     *
+     * @param $picUrl 图片地址
+     * @return int 错误码or 0(成功)
+     */
+    public function deleteAttachment($picUrl)
+    {
+        if ($this->fileDriver == 'local') {
+            $attachment = BaseAttachment::where(['path' => $picUrl])->first();
+            if (!$attachment) {
+                return false;
+            }
+            if (file_exists($attachment->path)) {
+                if (@unlink($attachment->path)) {
+                    if (!$attachment->delete()) {
+                        return false;
+                    }
+                } else {
+                    return false;
+                }
+            } else {
+                return false;
+            }
+        } elseif ($this->fileDriver == 'oss') {
+            $this->ossClient->deleteObject($this->bucket, $picUrl);
+        }
+
+        return true;
+    }
+
+}

+ 65 - 0
app/Helper/JpushHelper.php

xqd
@@ -0,0 +1,65 @@
+<?php
+namespace App\Helper;
+
+use JPush\Client as JPush;
+use App\Models\UserInfoModel;
+
+trait JpushHelper
+{
+    public function jPush($title,$content='',$userid=0,$type=0,$id=0) {
+        $app_key = '69838317211448192366f9d8';
+        $master_secret = 'f202d10301151e1816b49e55';
+        $client = new JPush($app_key, $master_secret, storage_path('logs/jpush.log'));
+
+        \Log::info('jpush start!');
+//        $push = new Push;
+//        $push->title = $title;
+//        $push->content = $content;
+//        $push->user_id = $userid;
+//        $res=$push->save();
+//        if($userid){
+            $user = UserInfoModel::find($userid);
+//        }
+        if($user&&$user->jpush){
+            $regId = array($user->jpush);
+            $options = array(
+                'apns_production' => true,
+            );
+            try {
+                $pusher = $client->push();
+                $pusher->setPlatform(['ios', 'android']);
+//                $pusher->addAllAudience();
+                $pusher->addRegistrationId($regId);
+                if($type!=0&&$id!=0){
+                    $pusher->androidNotification($title,[
+                        'title' => $content,
+                        'content_type' => 'text',
+                        'extras' => [
+                            'type' => $type,
+                            'id' => $id,
+                        ]
+                    ]);
+                    $pusher->iosNotification($title, [
+                        'sound' => 'sound',
+                        'badge' => '+1',
+                        'extras' => [
+                            'type' => $type,
+                            'id' => $id,
+                        ]
+                    ]);
+                }
+                $pusher->setNotificationAlert($title);
+                $pusher->options($options);
+                $pusher->send();
+                \Log::info('jpush send!');
+            } catch (\JPush\Exceptions\APIConnectionException $e) {
+                // try something here
+                \Log::error($e);
+            } catch (\JPush\Exceptions\APIRequestException $e) {
+                // try something here
+                \Log::error($e);
+            }
+        }
+    }
+
+}

+ 31 - 0
app/Helper/LogHelper.php

xqd
@@ -0,0 +1,31 @@
+<?php
+namespace App\Helper;
+
+use App\Models\AccountLog;
+
+trait LogHelper
+{
+    /**
+     * account log记录
+     * @param $data
+     * @return AccountLog
+     * @throws \Exception
+     */
+    private function logAccount($fromType, $fromId, $fromName, $fromAmount,  $op, $toType, $toId, $toName, $toAmount,$transactionId='',$avatar='') {
+        return AccountLog::create([
+            'from_type'     => $fromType,
+            'from_id'       => $fromId,
+            'from_name'     => $fromName,
+            'from_amount'   => $fromAmount,
+            'op'            => $op,
+            'to_type'       => $toType,
+            'to_id'         => $toId,
+            'to_name'       => $toName,
+            'to_amount'     => $toAmount,
+            'transaction_id'  => $transactionId,
+            'avatar'        => $avatar,
+        ]);
+    }
+
+
+}

+ 196 - 0
app/Helper/PayHelper.php

xqd
@@ -0,0 +1,196 @@
+<?php
+namespace App\Helper;
+
+use Omnipay\Omnipay;
+use App\Models\OrderInfoModel;
+use Config, Request,QrCode;
+
+trait PayHelper
+{
+    private function prepare() {
+//        Pingpp::setApiKey(env('PINGPP_APP_KEY'));
+//        Pingpp::setPrivateKeyPath(config_path() . 'ppp_pri_key.pem');
+    }
+
+    /**
+     * 验签
+     * @param $data
+     * @param $sig
+     * @return int
+     */
+    public function checkPppSignature($data, $sig) {
+        $pubKey = file_get_contents(config_path() . 'ppp_pub_key.pem');
+        return openssl_verify($data, $sig, $pubKey, 'sha256');
+    }
+
+    private function saveOrder($data) {
+        $order = new OrderInfoModel();
+        $order->code            = $data['code'];
+        $order->transaction_id  = $data['transaction_id'];
+        $order->user_id         = $data['user_id'];
+        $order->goods_id        = $data['goods_id'];
+        $order->price           = $data['price'];
+        $order->number          = $data['number'];
+        $order->amount          = $data['amount'];
+        $order->pay_type        = $data['pay_type'];
+        if (isset($data['ext_info'])) {
+            $order->ext_info = $data['ext_info'];
+        }
+
+        if ($order->save()) {
+            return $order->find($order->id);
+        }
+        return false;
+    }
+
+    public function createAlipayCharge($data, $profile = 'alipay') {
+        $gateways = Config::get('laravel-omnipay.gateways');
+        if (array_key_exists($profile, $gateways)) {
+            $config = $gateways[$profile];
+        } else {
+            \Log::error('alipay: 不支持的支付类型, ' . $profile);
+            return false;
+        }
+        $gateway = Omnipay::create($config['driver']);
+        $gateway->setEnvironment($config['options']['environment']);
+        $gateway->setAppId($config['options']['appid']);
+        $gateway->setEncryptKey($config['options']['encrypt_key']);
+        $gateway->setPrivateKey($config['options']['prikey']);
+        $gateway->setAlipayPublicKey($config['options']['ali_pubkey']);
+        $gateway->setNotifyUrl($config['options']['notify_url']);
+
+        $goodsTypes = OrderInfoModel::getAllGoodsTypes();
+        if (!isset($data['subject'])) {
+            $data['subject'] = sprintf("瞄喵%s充值%d", $goodsTypes[$data['goods']], $data['number']);
+        }
+        if (!isset($data['goods_id'])) {
+            $data['goods_id'] = 0;
+        }
+        $data['transaction_id'] = date('YmdHis') . mt_rand(1000, 9999);
+        $data['code'] = 'ALIPAY_' . $data['transaction_id'];
+        $data['price'] = 1;
+        $data['amount'] = $data['number'] * $data['price']*100;
+        $data['pay_type'] = OrderInfoModel::PAY_TYPE_ALIPAY;
+
+        $request = $gateway->purchase();
+        $request->setBizContent([
+            'subject'      => $data['subject'],
+            'out_trade_no' => $data['transaction_id'],
+            'total_amount' => round($data['amount'] / 100, 2),
+            'product_code' => 'QUICK_MSECURITY_PAY',//固定值
+        ]);
+        if ($profile == 'alipay_f2f') {
+            $request->setBizContent([
+                'subject'      => $data['subject'],
+                'out_trade_no' => $data['transaction_id'],
+                'total_amount' => round($data['amount'] / 100, 2),
+            ]);
+        }
+//        dd($request);
+
+        $response = $request->send();
+
+        if ($response->isSuccessful()) {
+            if ($profile == 'alipay_app' || $profile == 'alipay') {
+                $orderString = $response->getOrderString();
+            }
+            if ($profile == 'alipay_f2f') {
+                $code_url = $response->getQrCode();
+                $code_path = public_path('qrcodes/'.$data['code'].'.png');
+                QrCode::format('png')->size(500)->generate($code_url,$code_path);
+                $orderString =  env('APP_URL').'/qrcodes/'.$data['code'].'.png';
+            }
+            \Log::info("支付宝生成订返回:".$orderString);
+
+            //写订单
+            $order = $this->saveOrder($data);
+            if ($order !== false) {
+                $result = $order->toArray();
+                $result['orderString'] = $orderString;
+                return $result;
+            }
+            \Log::error('save order failed');
+            return false;
+        } else {
+            \Log::error('alipay response failed'.$response->getMessage());
+            return false;
+        }
+    }
+
+    public function createWechatpayCharge($data, $profile = 'wechatpay') {
+        $gateways = Config::get('laravel-omnipay.gateways');
+        if (array_key_exists($profile, $gateways)) {
+            $config = $gateways[$profile];
+        } else {
+            \Log::error('wechatpay: 不支持的支付设置, ' . $profile);
+            return false;
+        }
+
+        $gateway = Omnipay::create($config['driver']);
+//        $gateway->setEnvironment('sandbox');
+        $gateway->setAppId($config['options']['appid']);
+        $gateway->setMchId($config['options']['merchant_id']);
+        $gateway->setApiKey($config['options']['apikey']);
+        $gateway->setNotifyUrl($config['options']['notify_url']);
+
+        $goodsTypes = OrderInfoModel::getAllGoodsTypes();
+        if (!isset($data['subject'])) {
+            $data['subject'] = sprintf("瞄喵%s充值%d", $goodsTypes[$data['goods']], $data['number']);
+        }
+        if (!isset($data['goods_id'])) {
+            $data['goods_id'] = 0;
+        }
+        $data['transaction_id'] = date('YmdHis') . mt_rand(1000, 9999);
+        $data['code'] = 'WECHATPAY_' . $data['transaction_id'];
+        $data['price'] = 1;
+        $data['amount'] = $data['number'] * $data['price']*100;
+        $data['pay_type'] = OrderInfoModel::PAY_TYPE_WECHATPAY;
+
+        $order = [
+            'body'              => $data['subject'],
+            'out_trade_no'      => $data['transaction_id'],
+            'total_fee'         => $data['amount'],
+            'spbill_create_ip'  => Request::ip(),
+            'fee_type'          => 'CNY'
+        ];
+
+        $request  = $gateway->purchase($order);
+        $response = $request->send();
+
+//        dd($response);
+
+        if ($response->isSuccessful()) {
+            if ($profile == 'wechatpay_app' || $profile == 'wechatpay') {
+                $orderString = $response->getAppOrderData();
+            }
+//            if ($profile == 'wechatpay_native') {
+//                $code_url = $response->getCodeUrl();
+//                $code_path = public_path('qrcodes/'.$data['code'].'.png');
+//                QrCode::format('png')->size(500)->generate($code_url,$code_path);
+//                $orderString =  env('APP_URL').'/qrcodes/'.$data['code'].'.png';
+//            }
+            \Log::debug($orderString);
+
+            //写订单
+            $order = $this->saveOrder($data);
+            if ($order !== false) {
+                $result = $order->toArray();
+                $result['orderString'] = $orderString;
+                return $result;
+            }
+            \Log::error('save order failed');
+            return false;
+        } else {
+            \Log::error($response->getData());
+            return false;
+        }
+
+        //available methods
+//        $response->isSuccessful();
+//        $response->getData(); //For debug
+//        $response->getAppOrderData(); //For WechatPay_App
+//        $response->getJsOrderData(); //For WechatPay_Js
+//        $response->getCodeUrl(); //For Native Trade Type
+    }
+
+}

+ 332 - 0
app/Helper/function.php

xqd
@@ -0,0 +1,332 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: pijh
+ * Date: 2017/8/20
+ * Time: 00:33
+ */
+
+
+use Illuminate\Support\Arr;
+use \Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Storage;
+
+if (! function_exists('user_admin_config')) {
+    function user_admin_config($key = null, $value = null)
+    {
+        $session = session();
+
+        if (! $config = $session->get('admin.config')) {
+            $config = config('admin');
+
+            $config['lang'] = config('app.locale');
+        }
+
+        if (is_array($key)) {
+            // 保存
+            foreach ($key as $k => $v) {
+                Arr::set($config, $k, $v);
+            }
+
+            $session->put('admin.config', $config);
+
+            return;
+        }
+
+        if ($key === null) {
+            return $config;
+        }
+
+        return Arr::get($config, $key, $value);
+    }
+}
+
+//生成随机码
+function create_invite_code() {
+    $code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    $rand = $code[rand(0,25)]
+        .strtoupper(dechex(date('m')))
+        .date('d')
+        .substr(time(),-5)
+        .substr(microtime(),2,5)
+        .sprintf('%02d',rand(0,99));
+    for(
+        $a = md5( $rand, true ),
+        $s = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
+        $d = '',
+        $f = 0;
+        $f < 6;
+        $g = ord( $a[ $f ] ),
+        $d .= $s[ ( $g ^ ord( $a[ $f + 8 ] ) ) - $g & 0x1F ],
+        $f++
+    );
+    return $d;
+}
+
+/**
+ * 时间格式化(时间戳)
+ * @param $ptime
+ * @return false|string
+ */
+function uc_time_ago($ptime)
+{
+    date_default_timezone_set('PRC');
+    $etime = time() - $ptime;
+    switch ($etime) {
+        case $etime <= 60:
+            $msg = '刚刚';
+            break;
+        case $etime > 60 && $etime <= 60 * 60:
+            $msg = floor($etime / 60) . '分钟前';
+            break;
+        case $etime > 60 * 60 && $etime <= 24 * 60 * 60:
+            $msg = date('Ymd', $ptime) == date('Ymd', time()) ? '今天 ' . date('H:i', $ptime) : '昨天 ' . date('H:i', $ptime);
+            break;
+        case $etime > 24 * 60 * 60 && $etime <= 2 * 24 * 60 * 60:
+            $msg = date('Ymd', $ptime) + 1 == date('Ymd', time()) ? '昨天 ' . date('H:i', $ptime) : '前天 ' . date('H:i', $ptime);
+            break;
+        case $etime > 2 * 24 * 60 * 60 && $etime <= 12 * 30 * 24 * 60 * 60:
+            $msg = date('Y', $ptime) == date('Y', time()) ? date('m-d H:i', $ptime) : date('Y-m-d H:i', $ptime);
+            break;
+        default:
+            $msg = date('Y-m-d H:i', $ptime);
+    }
+    return $msg;
+}
+
+
+
+/**
+ * 获取IP地址归属地
+ * @param $ip
+ * @return string
+ */
+function get_ip_address($ip)
+{
+    if ('127.0.0.1' == $ip) return 'Localhost';
+    $url = 'http://ip.taobao.com/service/getIpInfo.php?ip=' . $ip;
+    $ch = curl_init($url);
+    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
+    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 获取数据返回
+    $location = curl_exec($ch);
+    $location = json_decode($location, true);
+    curl_close($ch);
+
+    if (false != $location && 0 === $location['code']) {
+        return $location['data']['region'] . $location['data']['city'] . $location['data']['county'] . '・' . $location['data']['isp'];
+    } else {
+        return 'unknown';
+    }
+
+}
+
+/**
+ * 递归查询获取分类树结构
+ * @param $data
+ * @param int $pid
+ * @param int $level
+ * @param array $tree
+ * @param string $pidField
+ * @param string $showField
+ * @return array
+ */
+function get_tree_list(&$data, $pid = 0, $level = 0, &$tree = [], $pidField = 'pid', $showField = 'name')
+{
+    foreach ($data as $key => &$value) {
+        if ($value[$pidField] == $pid) {
+            $value['level'] = $level;
+            $value['level'] && $value[$showField] = '&nbsp;' . $value[$showField];
+            $value[$showField] = str_repeat('ㅡ', $value['level']) . $value[$showField];
+            $tree[] = $value;
+            unset($data[$key]);
+            get_tree_list($data, $value['id'], $level + 1, $tree);
+        }
+    }
+    unset($value);
+
+    return $tree;
+}
+
+/**
+ * 递归查询获取分类树结构带child
+ * @param $data
+ * @param int $pid
+ * @param int $level
+ * @param string $pidField
+ * @return array
+ */
+function get_tree_list_with_child(&$data, $pid = 0, $level = 0, $pidField = 'pid')
+{
+    $tree = [];
+    foreach ($data as $key => &$value) {
+        if ($value[$pidField] == $pid) {
+            $value['level'] = $level;
+            $value['child'] = get_tree_list_with_child($data, $value['id'], $level + 1);
+            $tree[] = $value;
+            unset($data[$key]);
+        }
+    }
+    unset($value);
+
+    return $tree;
+}
+
+/**
+ * 打印sql语句,在sql语句之前调用
+ */
+function dump_sql()
+{
+    \DB::listen(function ($query) {
+        $bindings = $query->bindings;
+        $i = 0;
+        $rawSql = preg_replace_callback('/\?/', function ($matches) use ($bindings, &$i) {
+            $item = isset($bindings[$i]) ? $bindings[$i] : $matches[0];
+            $i++;
+            return gettype($item) == 'string' ? "'$item'" : $item;
+        }, $query->sql);
+        echo $rawSql . "\n<br /><br />\n";
+    });
+}
+
+function create_guid($namespace = null)
+{
+    static $guid = '';
+    $uid = uniqid("", true);
+
+    $data = $namespace;
+    $data .= $_SERVER ['REQUEST_TIME'];     // 请求那一刻的时间戳
+    $data .= $_SERVER ['HTTP_USER_AGENT'];  // 获取访问者在用什么操作系统
+    $data .= $_SERVER ['SERVER_ADDR'];      // 服务器IP
+    $data .= $_SERVER ['SERVER_PORT'];      // 端口号
+    $data .= $_SERVER ['REMOTE_ADDR'];      // 远程IP
+    $data .= $_SERVER ['REMOTE_PORT'];      // 端口信息
+
+    $hash = strtoupper(hash('ripemd128', $uid . $guid . md5($data)));
+    $guid = substr($hash, 0, 8);
+
+    return $guid;
+}
+
+function create_order_number()
+{
+    return date('Ymd') . str_pad(mt_rand(1, 999999), 6, '0', STR_PAD_LEFT);
+}
+
+/**
+ * curl 请求
+ * @param $url
+ * @param null $header
+ * @param null $data
+ * @return mixed
+ */
+function curlRequest($url, $header = null, $data = null)
+{
+    $ch = curl_init();
+    curl_setopt($ch, CURLOPT_URL, $url);
+    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+    curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
+    curl_setopt($ch, CURLOPT_HEADER, 1);
+    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+    if ($data) {
+        curl_setopt($ch, CURLOPT_POST, 1);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
+    }
+    if ($header) {
+        curl_setopt($ch, CURLOPT_HEADER, $header);
+    }
+    $ret = curl_exec($ch);
+    curl_close($ch);
+
+    return $ret;
+}
+
+/**
+ * 数字金额转换成中文大写金额的函数
+ * @param $num
+ * @return string
+ */
+function cny($num)
+{
+
+    $c1 = "零壹贰叁肆伍陆柒捌玖";
+    $c2 = "分角元拾佰仟万拾佰仟亿";
+    $num = round($num, 2);
+    $num = $num * 100;
+    if (strlen($num) > 10) {
+        return "数据太长,没有这么大的钱吧,检查下";
+    }
+    $i = 0;
+    $c = "";
+    while (1) {
+        if ($i == 0) {
+            $n = substr($num, strlen($num) - 1, 1);
+        } else {
+            $n = $num % 10;
+        }
+        $p1 = substr($c1, 3 * $n, 3);
+        $p2 = substr($c2, 3 * $i, 3);
+        if ($n != '0' || ($n == '0' && ($p2 == '亿' || $p2 == '万' || $p2 == '元'))) {
+            $c = $p1 . $p2 . $c;
+        } else {
+            $c = $p1 . $c;
+        }
+        $i = $i + 1;
+        $num = $num / 10;
+        $num = (int)$num;
+        if ($num == 0) {
+            break;
+        }
+    }
+    $j = 0;
+    $slen = strlen($c);
+    while ($j < $slen) {
+        $m = substr($c, $j, 6);
+        if ($m == '零元' || $m == '零万' || $m == '零亿' || $m == '零零') {
+            $left = substr($c, 0, $j);
+            $right = substr($c, $j + 3);
+            $c = $left . $right;
+            $j = $j - 3;
+            $slen = $slen - 3;
+        }
+        $j = $j + 3;
+    }
+
+    if (substr($c, strlen($c) - 3, 3) == '零') {
+        $c = substr($c, 0, strlen($c) - 3);
+    }
+    if (empty($c)) {
+        return "零元整";
+    } else {
+        return $c . "整";
+    }
+}
+
+if (!function_exists('valid_url')) {
+    /**
+     * 路径助手函数
+     * @param $url
+     * @param null $disk_name
+     * @param false $temp
+     * @param null|DateTimeInterface  $expiration
+     * @return string|null
+     */
+    function valid_url($url, $disk_name = null, $temp = false, $expiration = null)
+    {
+        if (is_null($url)) {
+            return null;
+        }
+
+        if (filter_var($url, FILTER_VALIDATE_URL)) {
+            return $url;
+        }
+
+        if ($temp) {
+            $expiration = $expiration ?: now()->addMinutes(30);
+            return Storage::disk($disk_name)->temporaryUrl($url, $expiration);
+        }
+
+        return Storage::disk($disk_name)->url($url);
+    }
+}
+

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

xqd
@@ -0,0 +1,42 @@
+<?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;
+use Illuminate\Http\Request;
+
+class Controller extends BaseController
+{
+    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
+
+    /**
+     * Validate the given request with the given rules.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  array  $rules
+     * @param  array  $messages
+     * @param  array  $customAttributes
+     * @return array
+     *
+     * @throws \Illuminate\Validation\ValidationException
+     */
+    public function validate(Request $request, array $rules,
+                             array $messages = [], array $customAttributes = [])
+    {
+        $validate = [];
+        foreach ($rules as $k => $v){
+            $tmp = explode('|', $k);
+            $validate[$tmp[0]] = $v;
+            if (!empty($tmp[1]) && empty($customAttributes[$tmp[0]])){
+                $customAttributes[$tmp[0]] = $tmp[1];
+            }
+        }
+
+        return $this->getValidationFactory()->make(
+            $request->all(), $validate, $messages, $customAttributes
+        )->validate();
+    }
+}

+ 39 - 0
app/Http/Controllers/V1/ArticleController.php

xqd
@@ -0,0 +1,39 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+use App\Models\Help;
+use App\Models\Region;
+use Illuminate\Http\Request;
+use App\Models\Advertise;
+use App\Models\Setting;
+use Hamcrest\Type\IsString;
+use Illuminate\Support\Facades\Redis;
+use Illuminate\Support\Facades\Validator;
+
+class ArticleController extends Controller
+{
+    //帮助类型
+    public function helpList()
+    {
+        $list = Help::query()->select('id', 'title')->get();
+
+        if($list->isEmpty()){
+            return [];
+        }
+        $list = $list->toArray();
+
+        return $this->success($list);
+    }
+
+    //帮助类答案
+    public function answer(Request $request)
+    {
+        $info = Help::query()->where('id', $request->id)->first();
+        $info->look_num = $info->look_num +1;
+        $info->save();
+
+        return $this->success($info);
+    }
+
+}

+ 87 - 0
app/Http/Controllers/V1/AttachmentController.php

xqd
@@ -0,0 +1,87 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+use Illuminate\Http\Request;
+//use App\Helper\AttachmentHelper;
+use App\Services\Base\ErrorCode;
+use App\Services\AttachmentServer;
+use Illuminate\Support\Facades\Validator;
+
+
+class AttachmentController extends Controller
+{
+    //use AttachmentHelper;
+
+    /**
+     * * 可能出现的错误代码:
+     *    200     SAVE_USER_FAILED                保存用户数据失败
+     *    201     ATTACHMENT_MKDIR_FAILED         创建附件目录失败
+     *    202     ATTACHMENT_UPLOAD_INVALID       上传附件文件无效
+     *    203     ATTACHMENT_SAVE_FAILED          保存附件失败
+     *    204     ATTACHMENT_MOVE_FAILED          移动附件失败
+     *    205     ATTACHMENT_DELETE_FAILED        删除附件文件失败
+     *    206     ATTACHMENT_RECORD_DELETE_FAILED 删除附件记录失败
+     *    1000    CLIENT_WRONG_PARAMS             传入参数不正确
+     *    1101    INCORRECT_VERIFY_CODE           输入验证码错误
+     *    1105    USER_DOES_NOT_EXIST             用户不存在
+     *    1200    ATTACHMENT_UPLOAD_FAILED        附件上传失败
+     *    1201    ATTACHMENT_SIZE_EXCEEDED        附件大小超过限制
+     *    1202    ATTACHMENT_MIME_NOT_ALLOWED     附件类型不允许
+     *    1203    ATTACHMENT_NOT_EXIST            附件不存在
+     * @param Request $request
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function upload(Request $request)
+    {
+        try {
+            $validator = Validator::make($request->all(),
+                [
+                    'tag' => 'required|alpha_dash',
+                ], [
+                    'tag.required' => 'tag必填',
+                    'tag.alpha_dash' => 'tag只能为字母数字中/下划线',
+                ]
+            );
+            if ($validator->fails()) {
+                throw new \Exception($validator->messages()->first());
+            }
+            $result = (new AttachmentServer())->uploadAttachment($request, $request->post('file'), $request->post('tag'), 10 * 1024 * 1024, [
+                'image/jpeg',
+                'image/png',
+                'image/gif',
+                'video/mp4',
+            ]);
+        } catch (\Exception $exception) {
+            return $this->error($exception->getMessage());
+        }
+        return $this->success(['file' => $result], 0, trans("api.UPLOAD_SUCCESS"));
+    }
+
+    /**
+     * @param Request $request
+     * @return \Illuminate\Http\JsonResponse
+     * parse_url($url);
+     * array (
+            'scheme' => 'https',
+            'host'   => 'zhengda.oss-cn-chengdu.aliyuncs.com',
+            'path'   => '/api_avatar/2022-07/14/1271657787068220714.jpeg',
+       )
+     */
+    public function delete(Request $request)
+    {
+        $picUrl = $request->pic_url;
+        if(empty($picUrl)){
+            return $this->error('路径必填!');
+        }
+        $arr  = parse_url($picUrl);
+        $path = substr($arr['path'], 1);
+        $result = (new AttachmentServer())->deleteAttachment($path);
+        if ($result) {
+            return $this->success([]);
+        } else {
+            return $this->error('',ErrorCode::ATTACHMENT_DELETE_FAILED);
+        }
+    }
+
+}

+ 313 - 0
app/Http/Controllers/V1/AuthController.php

xqd
@@ -0,0 +1,313 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+use App\Models\Job;
+use App\Models\User;
+use App\Services\Api\CommonService;
+use App\Services\Api\ErrorMsgServive;
+use App\Services\Api\UserService;
+use App\Services\JPushService;
+use App\Services\SmsServer;
+use Cache;
+use EasyWeChat\Factory;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\DB;
+use Laravel\Socialite\Facades\Socialite;
+use PHPUnit\Util\Exception;
+use Illuminate\Support\Facades\Validator;
+
+class AuthController extends Controller
+{
+    public function __construct()
+    {
+        $this->wxConfig = ['app_id' => env("WECHAT_MINI_PROGRAM_APPID"), 'secret' => env("WECHAT_MINI_PROGRAM_SECRET"), 'response_type' => 'array'];
+    }
+    //注册
+    public function register(Request $request)
+    {
+        $account   = $request->input('account', '');
+        $password = $request->input('password', '');
+        $passwords = $request->input('passwords', '');
+        $validator = Validator::make($request->all(), [
+            'account' => 'required',
+            'name' => 'required|alpha_num',
+            'email' => 'required',
+            'password' => 'required|min:6',
+            'passwords' => 'required|min:6',
+        ]);
+        if ($validator->fails()) {
+            return $this->error($validator->errors()->first());
+        }
+        if($password != $passwords){
+            return $this->error('密码不一致!');
+        }
+        // 查询用户是否存在
+        $user = User::query()
+            ->where('account','=',$account)
+            ->first();
+        if($user){
+            return $this->error('账号已存在!');
+        }
+        if (CommonService::is_email($request->email)){ // 邮箱格式
+            if(!EmailController::isEmailCodeRight($request->email,$request->code)){
+                return $this->error("验证码验证失败!");
+            }
+        }else{
+            return $this->error('账号格式不正确!');
+        }
+        $user = \App::make('getUserInstance'); //在 app/Providers/AppServiceProvider.php 里面可以创一个单例模式
+        $user->name = $request->name; // 姓名
+        $user->account = $request->account; // 账号
+        $user->email = $request->email; // 邮箱
+        $user->password = $password; //这个不是直接存密码,User模型中使用了修改器
+        $user->register_ip = request()->ip();
+        $user->save();
+        return $this->success('创建成功!');
+    }
+
+    //账号密码登录
+    public function login(Request $request)
+    {
+        $account = $request->input('account');
+        $password = $request->input('password');
+        $jpush_reg_id = $request->input('jpush_reg_id');
+        if (!$user = User::query()->where('account','=',$account)->first()) {
+            return $this->error('账号不存在');
+        }
+        // 账号是否禁用
+        if($user->status == 0){
+            return $this->error('账号已被禁用!');
+        }
+        $credentials1 = ['account' => $account, 'password' => $password];
+        if (!auth('api')->attempt($credentials1)) {
+            return $this->error('密码错误!');
+        }
+        $data = $this->doLogin($user, $jpush_reg_id);
+        return $this->success($data);
+    }
+
+    //短信验证码登录
+    public function loginBySmsCode(Request $request)
+    {
+        try {
+            if (!$user = User::query()->where(['mobile' => $request->mobile])->first()) {
+              return $this->error('账号不存在');
+            }
+            //手机验证码验证
+            SmsServer::checkSmsCodeByVerifyKey($request->mobile, $request->smsCode);
+            //如果登录类型和 openid 不为空
+            $type = $request->type;
+            if (isset($type) && !empty($type)) {
+                if ($type == 'weixin') {
+                    if ($user->wx_openid != '') {
+                      return $this->error('已经绑定微信');
+                    }
+                    $user->wx_openid = $request->openid;
+                    $user->save();
+                }
+            }
+            $data = $this->doLogin($request->mobile, $request->post('jpush_reg_id', ''));
+        } catch (\Exception $exception) {
+            return $this->error($exception);
+        }
+        return $this->success($data);
+    }
+
+    //APP第三方授权登录(微信)
+    public function authLogin(Request $request)
+    {
+        try {
+            $socialite = Socialite::driver('weixin')->stateless()->user();
+            $user = User::query()->where('open_id', $socialite->getId())->first();
+            if (!$user) {
+                $data['open_id'] = $socialite->getId();
+                $data['user'] = [];
+            } else {
+                $account = $user->mobile ?: $user->email;
+                $data = $this->doLogin($account, $request->post('jpush_reg_id', ''));
+            }
+        } catch (Exception $exception) {
+            ErrorMsgServive::write($exception, requst()->url());
+            return $this->error('微信授权登录出错~');
+        }
+        return $this->success($data);
+    }
+
+    //微信小程序登录(微信)
+    public function miniProgram(Request $request)
+    {
+        try {
+            $mini = Factory::miniProgram($this->wxConfig);
+            $newMini = $mini->auth->session($request->input('code'));
+
+            $iv = $request->input('iv');
+            $encryptData = $request->input('encryptData');
+            $decryptedData = $mini->encryptor->decryptData($newMini['session_key'], $iv, $encryptData);
+            $openId = $decryptedData['openid'];
+            $user = User::query()->where('open_id', $openId)->first();
+            if (!$user) {
+                $data['open_id'] = $openId;
+                $data['user'] = [];
+            } else {
+                $account = $user->mobile ?: $user->email;
+                $data = $this->doLogin($account, $request->post('jpush_reg_id', ''));
+            }
+        } catch (Exception $exception) {
+            ErrorMsgServive::write($exception, requst()->url());
+            return $this->error('微信授权登录出错~');
+        }
+        return $this->success($data);
+    }
+
+    //微信小程序获取手机号
+    public function decryptPhone(Request $request)
+    {
+        $user = auth('api')->user();
+        try {
+            $mini = Factory::miniProgram($this->wxConfig);
+            $newMini = $mini->auth->session($request->input('code'));
+
+            $iv = $request->input('iv');
+            $encryptData = $request->input('encryptData');
+            $decryptedData = $mini->encryptor->decryptData($newMini['session_key'], $iv, $encryptData);
+
+            $user = User::query()->where('id', $user->id)->first();
+            $user->mobile = $decryptedData['purePhoneNumber'];
+            $user->save();
+        } catch (\Exception $exception) {
+            ErrorMsgServive::write($exception, requst()->url());
+            return $this->error('获取手机号出错~');
+        }
+        return $this->success();
+    }
+
+    //H5 应用进行微信授权登录
+    public function h5Oauth()
+    {
+
+    }
+
+    //微信小程序 code
+    public function miniCode()
+    {
+
+    }
+
+    //执行登录
+    public function doLogin($user, $jpush_reg_id = null)
+    {
+        if (!empty($jpush_reg_id)) {
+            //清除登陆过本设备的账号设备id
+            User::query()->where('jpush_reg_id', $jpush_reg_id)->update(['jpush_reg_id' => '']);
+            //当前登录用户绑定设备
+            $user->jpush_reg_id = $jpush_reg_id;
+            //清除别名
+            JPushService::deleteAlias('user_id_' . $user->id);
+            //设置极光推送别名
+            JPushService::updateAlias($user->jpush_reg_id, 'user_id_' . $user->id);
+        }
+        $user->online = 1;
+        $user->last_login_time = date('Y-m-d H:i:s');
+        $user->last_login_ip = request()->ip();
+        if (!$user->save()) {
+            return $this->error('登录失败!');
+        }
+        $token = Auth::guard('api')->fromUser($user);
+        $userInfo = UserService::getUserInfoById($user->id);
+        $data = [
+            'token' => "Bearer " . $token,
+            'user_info' => $userInfo,
+        ];
+        return $data;
+    }
+
+    //用户是否存在
+    public function isUserExist($account)
+    {
+        $user = User::where(['mobile' => $account])
+            ->orWhere(['email' => $account])
+            ->first();
+        if (!$user) {
+            return false;
+        }
+        return $user;
+    }
+
+    //忘记密码
+    public function forgetPassword(Request $request)
+    {
+        $account   = $request->input('account', '');
+        $validator = Validator::make($request->all(), [
+            'account' => 'required',
+        ]);
+        if ($validator->fails()) {
+            return $this->error($validator->errors()->first());
+        }
+        // 查询用户是否存在
+        $user = User::query()
+            ->where('account','=',$account)
+            ->first();
+        if(!$user){
+            return $this->error('账号不存在!');
+        }
+        if($user->status == 0){
+            return $this->error('账号已被禁用!');
+        }
+        // 随机生成密码
+        $password = rand(100000, 999999);
+        $content = '您找回的密码为系统重新生成:'.$password.',登录后请自行修改!';
+        $res = EmailController::sendNotice($user->email,'找回密码通知',$content);
+        if(!$res){
+            return $this->error("找回密码失败!");
+        }
+        $user->password = $password; // 处理过加密的
+        $user->save();
+        return $this->success('',0,'我们已将密码发至您的电子邮件!');
+    }
+
+    //找回ID
+    public function findId(Request $request)
+    {
+        $email   = $request->input('email', '');
+        $validator = Validator::make($request->all(), [
+            'email' => 'required',
+        ]);
+        if ($validator->fails()) {
+            return $this->error($validator->errors()->first());
+        }
+        // 查询用户是否存在
+        $user = User::query()
+            ->where('email','=',$email)
+            ->first();
+        if(!$user){
+            return $this->error('邮箱不存在!');
+        }
+        if($user->status == 0){
+            return $this->error('账号已被禁用!');
+        }
+        $content = '您找回的ID为:'.$user->account.',请妥善保存!';
+        $res = EmailController::sendNotice($user->email,'找回ID通知',$content);
+        if(!$res){
+            return $this->error("找回ID失败!");
+        }
+        return $this->success('',0,'我们已将ID发至您的电子邮箱!');
+    }
+
+    //退出
+    public function logout()
+    {
+        $user = auth('api')->user();
+        if($user){
+            if(!empty($user->jpush_reg_id)){
+                //清空极光别名
+                JPushService::updateAlias($user->jpush_reg_id, '');
+            }
+            $user->online = 0;
+            $user->save();
+        }
+        auth('api')->logout();
+        return $this->success('',0,'退出成功!');
+    }
+}

+ 33 - 0
app/Http/Controllers/V1/BaseConfigController.php

xqd
@@ -0,0 +1,33 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+use App\Models\BaseConfig;
+
+class BaseConfigController extends Controller
+{
+    /**
+     * UserController constructor.
+     */
+    public function __construct()
+    {
+        $this->middleware('check', ['except' => ['index']]);
+    }
+
+    /**
+     * 获取配置
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function index()
+    {
+        $lang = request('lang', 'cn');
+        $group = request('group');
+        if (!$group) {
+            return json(201, trans("api.Parameter", [], $lang));
+        }
+        $key = request('key', '');
+        $arr = BaseConfig::get($group, $key, "");
+
+        return json(200,'BaseConfig Info', $arr);
+    }
+}

+ 94 - 0
app/Http/Controllers/V1/Controller.php

xqd
@@ -0,0 +1,94 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+use Dingo\Api\Routing\Helpers;
+use Illuminate\Foundation\Bus\DispatchesJobs;
+use Illuminate\Routing\Controller as BaseController;
+use Illuminate\Foundation\Validation\ValidatesRequests;
+use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
+use App\Services\Base\ErrorCode;
+use Request, Auth, Log;
+
+class Controller extends BaseController
+{
+    use AuthorizesRequests, DispatchesJobs, ValidatesRequests, Helpers;
+
+    //验证器错误信息返回
+    public function validatorError($arr, $code = 0, $msg = '')
+    {
+        //写入日志
+        Log::info($arr);
+        //获取返回信息
+        foreach ($arr as $val){
+            if($val&&$msg==''){
+                $msg = $val;
+            }
+        }
+        //组装状态码和返回信息
+        $res = [
+            'code' => $code,
+            'msg'  => $msg ?? '',
+            'data' => null
+        ];
+        //json返回数据和状态码
+        return response()->json($res);
+    }
+
+    //通用输出方法
+    public function output($data=[], $code = 0, $msg = '')
+    {
+        $ret = $this->makeApiData($data, $code, $msg);
+        return response()->json($ret);
+    }
+
+    //正确返回
+    public function success($data=[], $code = 0, $msg = '')
+    {
+        //是否有成功时返回的信息
+        if (!$msg) $msg = trans('api.SUCCESS');
+        //组装状态码返回信息等数据
+        $ret = $this->makeApiData($data, $code, $msg);
+        //返回json数据
+        return response()->json($ret);
+    }
+
+    //错误返回
+    public function error($msg = '', $code = 1,  $data = null)
+    {
+        $ret = $this->makeApiData($data, $code, $msg);
+        return response()->json($ret);
+    }
+
+    //生成返回数据
+    private function makeApiData($data, $code = 0, $message = '')
+    {
+        //判断状态码是否正常和返回信息是否为空
+        if ($code !== 0 && empty($message)) {
+            //输出错误码对应的错误信息
+            $message = ErrorCode::message($code);
+        } else if ($code == 0 && empty($message)) {
+            //输出成功信息
+            $message = 'success';
+        }
+        //组装数据
+        $ret = [
+            'code' => $code,
+            'msg'  => $message,
+            'data' => $data
+        ];
+        //返回数据
+        return $ret;
+    }
+
+    // 分页
+    public function page($list){
+        return [
+            'items' =>$list->items(),
+            'total'=>$list->total(),   // 总数
+            'pageSize'=>$list->perPage(), // 每页数据
+            'totalPage'=>$list->lastPage(),// 总页数
+            'page'=>$list->currentPage(),//当前页
+        ];
+    }
+}

+ 102 - 0
app/Http/Controllers/V1/EmailController.php

xqd
@@ -0,0 +1,102 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+use App\Models\User;
+use App\Services\Api\ErrorMsgServive;
+use Illuminate\Http\Request;
+use Illuminate\Support\Carbon;
+use Illuminate\Support\Facades\Mail;
+use App\Models\MailCode;
+use Illuminate\Support\Facades\Validator;
+
+class EmailController extends Controller
+{
+    /**
+     发送邮箱验证码
+     在 .env 文件配置如下,可测试邮件发送(最好自己申请一个邮箱获取信息)
+     MAIL_MAILER=smtp
+     MAIL_HOST=ssl://smtp.163.com
+     MAIL_PORT=465
+     MAIL_USERNAME=18738190585@163.com
+     MAIL_PASSWORD=VIBTDHQAYLKJYIGC
+     MAIL_ENCRYPTION=
+     MAIL_FROM_ADDRESS=18738190585@163.com
+     MAIL_FROM_NAME="${APP_NAME}"
+     *
+     * @param Request $request
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function sendEmailCode(Request $request)
+    {
+        $email = $request->input('email');
+
+        $validator = Validator::make($request->all(), [
+            'email' => 'required|email',
+        ]);
+        if ($validator->fails()) {
+            return $this->error($validator->errors()->first());
+        }
+        $code = rand(1000, 9999);
+        $notice = '本次验证码是' . '【 ' . $code . ' 】 ' . '有效期 5 分钟';
+        $subject = '邮箱验证通知';
+        try {
+            Mail::raw($notice, function ($message) use ($email, $subject) {
+                $message->subject($subject);
+                $message->to($email);
+            });
+            $mailCode = new MailCode();
+            $mailCode->account = $email;
+            $mailCode->code = $code;
+            $mailCode->state = 0;
+            $mailCode->created_at = date('Y-m-d H:i:s');
+            $mailCode->save();
+            return $this->success();
+        } catch (\Exception $e) {
+            return $this->error($e->getMessage());
+        }
+    }
+
+    //判断邮箱验证码 5分钟有效期 (这不是个API接口:哪里需要就放到哪里验证)
+    public static function isEmailCodeRight($email, $code)
+    {
+        $result = MailCode::query()
+            ->where('account', $email)
+            ->where('code', $code)
+            ->where('state', 0)
+            ->where('created_at', '>', Carbon::now()->subMinutes(5))
+            ->orderBy('id', 'desc')
+            ->first();
+
+        if (!$result) {
+            return false;
+        }
+        $result->state = 1; //验证通过就失效
+        $result->save();
+
+        return true;
+    }
+
+
+    /**
+     * @param $email
+     * @param $title
+     * @param $notice
+     * @return bool
+     * 邮箱发送通知
+     */
+    public static function sendNotice($email = null,$title = null, $notice = null)
+    {
+        try {
+            Mail::raw($notice, function ($message) use ($email, $title) {
+                $message->subject($title);
+                $message->to($email);
+            });
+            return true;
+        } catch (\Exception $e) {
+            return false;
+        }
+    }
+
+
+}

+ 38 - 0
app/Http/Controllers/V1/IndexController.php

xqd
@@ -0,0 +1,38 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+use App\Models\Help;
+use App\Models\Region;
+use Illuminate\Http\Request;
+use App\Models\Advertise;
+use App\Models\Setting;
+use Illuminate\Support\Facades\Redis;
+
+class IndexController extends Controller
+{
+    //隐私政策
+    public function privacyPolice()
+    {
+        $info = Setting::where('key', 'privacy')->where('is_delete', 0)->select('title', 'key', 'value')->first();
+
+        return $this->success($info);
+    }
+
+    //用户协议
+    public function userAgreement()
+    {
+        $info = Setting::where('key', 'agreement')->where('is_delete', 0)->select('title', 'key', 'value')->first();
+
+        return $this->success($info);
+    }
+
+    //关于我们
+    public function aboutus()
+    {
+        $info = Setting::where('key', 'aboutus')->where('is_delete', 0)->select('title', 'key', 'value')->first();
+
+        return $this->success($info);
+    }
+
+}

+ 74 - 0
app/Http/Controllers/V1/MemberController.php

xqd
@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+use App\Models\User;
+use App\Models\UserMember;
+use App\Models\UserMemberOrder;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+
+/**
+ * 会员
+ */
+class MemberController extends Controller
+{
+    public function __construct()
+    {
+        $this->user = auth('api')->user();
+        $this->userId = $this->user ? $this->user->id : 0;
+
+        //如果用户被删除,会自动退出登录
+        if (!empty($this->user->deleted_at)) {
+            $this->user->online = 0;
+            $this->user->save();
+            auth('api')->logout();
+        }
+    }
+
+    /**
+     * @return void
+     * 会员选项
+     */
+    public function memberList(Request $request){
+
+        $list = UserMember::query()->get();
+
+        return $this->success($list);
+
+    }
+
+    /**
+     * @return void
+     * 加入会员
+     */
+    public function joinMember(Request $request){
+        $params = $request->all();
+        DB::beginTransaction();
+        try {
+            $user = User::query()->where('id',$this->userId)->first();
+            $data = [
+                'user_id' => $this->userId,
+                'days' => 30,// 续费时间 = 默认一个月30天
+                'money' => UserMember::query()->where('id',2)->value('money') // 续费金额
+            ];
+            $order = UserMemberOrder::query()->create($data);
+            $user->update($params);
+            DB::commit();
+        } catch (\Exception $e){
+            DB::rollBack();
+           return $this->error("保存失败!");
+        }
+       return $this->success($order);
+    }
+
+    /**
+     * @return void
+     * 支付构建
+     */
+    public function payment(){
+
+        
+
+    }
+
+}

+ 436 - 0
app/Http/Controllers/V1/PayController.php

xqd
@@ -0,0 +1,436 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+use Omnipay\Omnipay;
+use App\Helper\LogHelper;
+use App\Helper\PayHelper;
+use App\Helper\JpushHelper;
+use App\Models\User;
+use App\Models\order;
+use App\Models\AccountLog;
+use App\Services\Base\ErrorCode;
+use Illuminate\Support\Facades\Request;
+use Illuminate\Support\Facades\Validator;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Config;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Log;
+
+
+class PayController extends Controller
+{
+    use PayHelper, LogHelper,JpushHelper;
+
+    public function alipayNotify() {
+        $rawInfo = Request::all();
+        Log::info('aliplay callback');
+        Log::info($rawInfo);
+
+        $config = Config::get('laravel-omnipay.gateways.alipay');
+
+        $gateway = Omnipay::create($config['driver']);
+        print_r($gateway);exit;
+        $gateway->setEnvironment($config['options']['environment']);
+        $gateway->setAppId($config['options']['appid']);
+        $gateway->setEncryptKey($config['options']['encrypt_key']);
+        $gateway->setPrivateKey($config['options']['prikey']);
+        $gateway->setAlipayPublicKey($config['options']['ali_pubkey']);
+        $gateway->setNotifyUrl($config['options']['notify_url']);
+
+        $request = $gateway->completePurchase();
+        $request->setParams($rawInfo);//Optional
+
+        try {
+            $response = $request->send();
+
+            if($response->isPaid()){
+              echo 1;exit;
+//                 Log::info('支付成功');
+
+//                 $out_trade_no = $rawInfo['out_trade_no'];
+//                 $order = Order::where('transaction_id', '=', $out_trade_no)->first();
+//                 if (!$order) {
+//                     Log::error('找不到订单' . $out_trade_no);
+//                     return 'fail';
+//                 }
+//                 $master_amount =  $order->number;
+//                 $slave_amount = 0;
+//                 if (!empty($order->ext_info)) {
+//                     $extInfo = json_decode($order->ext_info, true);
+//                     if ($extInfo !== null) {
+//                         $cc = $extInfo['cc_bonus'];
+//                         $master_amount = round(($cc / 100) * $order->number);
+//                         $slave_amount = $order->number - $master_amount;
+//                     }
+//                 }
+//                 $tp = '';
+// //                $u = null;
+//                 if ($order->user_type == Order::USER_TYPE_MERCHANT) {
+//                     $tp = 'Merchant';
+// //                    $u = Merchant::find($order->user_id);
+//                 } elseif ($order->user_type == Order::USER_TYPE_MEMBER) {
+//                     $tp = 'Member';
+//                     //Not handled here
+//                 }
+//                 $u = User::find($order->user_id);
+//                 if (!$u) {
+//                     Log::error('用户不存在' . $order->user_type . ', ' . $order->user_id);
+//                     return 'success';
+//                 }
+
+//                 DB::beginTransaction();
+
+//                 if ($order->goods_type == Order::GOODS_TYPE_BALANCE||$order->goods_type == Order::GOODS_TYPE_COSUME) {
+//                     $cType = AccountLog::TYPE_BALANCE;
+// //                    $u->account_balance += $order->number;
+//                     $u->balance += $master_amount;
+//                 } elseif ($order->goods_type == Order::GOODS_TYPE_CREDIT) {
+//                     $cType = AccountLog::TYPE_CREDIT;
+// //                    $u->credit_balance += $order->number;
+//                     $u->credit += $master_amount;
+//                 } else {
+//                     Log::error('商品不存在' . $order->goods_type);
+//                     return 'success';
+//                 }
+//                 Log::info('支付金额 '.$master_amount);
+//                 if ($u->save()) {
+
+//                     //更新订单状态
+//                     $order->status = Order::STATUS_FINISHED;
+//                     $order->save();
+
+//                     //记日志
+//                     $amount = $rawInfo['total_amount'] * 100;
+//                     $_ops = AccountLog::getAllop();
+//                     $this->logAccount($tp, $u->id, $u->name,
+//                             AccountLog::OP_CHARGE, $cType, $master_amount,
+//                             AccountLog::DIRECTION_INC, $cType == AccountLog::TYPE_BALANCE ? $u->balance : $u->credit, AccountLog::CHANNEL_ALIPAY);
+
+//                     Log::info('支付完成');
+
+//                 } else {
+//                     DB::rollBack();
+//                     Log::error('保存数据失败');
+//                 }
+
+//                 DB::commit();
+
+//                 return 'success';
+            }else{
+                Log::error('支付失败');
+
+                return 'fail';
+            }
+        } catch (\Exception $e) {
+            Log::error('支付异常' . $e->getMessage());
+
+            return 'fail';
+        }
+
+    }
+
+    public function wechatpayNotify() {
+        Log::debug('wechatpay callback');
+//        Log::debug(Request::all());
+
+        $config = Config::get('laravel-omnipay.gateways.wechatpay');
+
+        $gateway = Omnipay::create("WechatPay");
+//        $gateway->setEnvironment('sandbox');
+        $gateway->setAppId($config['options']['appid']);
+        $gateway->setMchId($config['options']['merchant_id']);
+        $gateway->setApiKey($config['options']['apikey']);
+
+        $response = $gateway->completePurchase([
+            'request_params' => file_get_contents('php://input')
+        ])->send();
+        try {
+            if ($response->isPaid()) {
+                //pay success
+                // $rawInfo = $response->getRequestData();
+                // Log::debug($rawInfo);
+                // Log::info('支付成功');
+
+                // $out_trade_no = $rawInfo['out_trade_no'];
+                // $order = order::where('transaction_id', '=', $out_trade_no)->first();
+                // if (!$order) {
+                //     Log::error('找不到订单' . $out_trade_no);
+                //     return 'fail';
+                // }
+                // $u = User::find($order->user_id);
+                // if (!$u) {
+                //     Log::error('用户不存在' . $order->user_id . ', ' . $order->user_id);
+                //     return 'success';
+                // }
+
+                // DB::beginTransaction();
+                // $u->coin += $order->number;
+                // if ($u->save()) {
+
+                //     //更新订单状态
+                //     $order->status = order::STATUS_FINISHED;
+                //     $order->save();
+
+                //     //记日志
+                //     $_types = AccountLog::getAllType();
+                //     $_ops = AccountLog::getAllop();
+                //     $this->logAccount($_types[AccountLog::TYPE_CASH], $u->id, $u->name,$order->amount,
+                //         $_ops[AccountLog::OP_CHARGE],
+                //         $_types[AccountLog::TYPE_COIN], $u->id,$u->name,$order->amount,$out_trade_no,'http://miao.beiyuesi.com/base/img/wechat.png');
+
+                //     Log::info('支付完成');
+
+                // } else {
+                //     DB::rollBack();
+                //     Log::error('保存数据失败');
+                // }
+
+                // DB::commit();
+
+                // return 'success';
+            }else{
+                //pay fail
+                Log::error($response->getData());
+                return 'fail';
+            }
+
+        } catch (\Exception $e) {
+            Log::error('支付异常' . $e->getMessage());
+
+            return 'fail';
+        }
+    }
+
+
+
+    /**
+     * @api {post} /api/pay/charge 充值
+     * @apiDescription 充值(向平台充值)
+     * @apiGroup User
+     * @apiPermission Passport
+     * @apiVersion 0.1.0
+     * @apiParam {int}  [goods=1]   充值商品(1:梦想币)
+     * @apiParam {int}  number      充值数量,人民币,以分表示
+     * @apiParam {int}  type        支付类型(1:支付宝,2:微信支付)
+     * @apiSuccessExample {json} Success-Response:
+     * HTTP/1.1 200 OK
+     * {
+     *     "state": true,
+     *     "code": 0,
+     *     "message": "",
+     *     "data": {
+     *         "id": 2,
+     *         "code": "ALIPAY_201610231314145719",
+     *         "transaction_id": "201610231314145719",
+     *         "user_type": 2,
+     *         "user_id": 1,
+     *         "goods_type": 1,
+     *         "price": 1,
+     *         "number": 1,
+     *         "amount": 1,
+     *         "pay_type": 1,
+     *         "status": 0,
+     *         "created_at": "2016-10-23 13:14:14",
+     *         "updated_at": "2016-10-23 13:14:14",
+     *         "orderString": "alipay_sdk=lokielse%2Fomnipay-alipay&app_id=2016091201894867&biz_content=%7B%22subject%22%3A%22%5Cu7532%5Cu8c61%5Cu8054%5Cu5408-%5Cu4f59%5Cu989d%5Cu5145%5Cu503c%22%2C%22out_trade_no%22%3A%22201610231314145719%22%2C%22total_amount%22%3A0.01%2C%22product_code%22%3A1%7D&charset=UTF-8&format=JSON&method=alipay.trade.app.pay&notify_url=http%3A%2F%2Fweb%2Fapi%2Fpay%2Falipay%2Fnotify&sign_type=RSA&timestamp=2016-10-23+13%3A14%3A14&version=1.0&sign=oxKM0qGMHLWDlMrXHIiy9%2Fk2BXJq3rC3RKdmcfFwkBJVRXvtG6cBoAYPll6VxJYOMQWeu78Ibfov%2FxIVCuN9yUfzEiokfQrzBoptc94bCQ5k0pNyJcSdgezOUKHB12P5Zmm3Hd6AAbGRDV9UCaLVz0wYkFJPrCyUv1ZfhrM%2BBqc%3D"
+     *     }
+     * }
+     * @apiErrorExample {json} Error-Response:
+     * HTTP/1.1 400 Bad Request
+     * {
+     *     "state": false,
+     *     "code": 1000,
+     *     "message": "传入参数不正确",
+     *     "data": null or []
+     * }
+     * 可能出现的错误代码:
+     * 1000    CLIENT_WRONG_PARAMS             传入参数不正确
+     */
+    public function charge(Request $request)
+    {
+        $goodsTypes = order::getAllGoodsTypes();
+        $gTypes = array_keys($goodsTypes);
+        $payTypes = order::getAllPayTypes();
+        $pTypes = array_keys($payTypes);
+        $validator = Validator::make($data = $request->all(),
+            [
+                'number' => 'required|integer|min:1',
+                'type' => 'required|in:' . join(',', $pTypes),
+                'goods' => 'in:' . join(',', $gTypes),
+            ],
+            [
+                'number.required' => '请输入梦想币数量',
+                'number.integer' => '梦想币数量必须为整数',
+                'number.min' => '充值梦想币数量至少为1',
+                'type.required' => '支付类型必填',
+                'type.in' => '支付类型非法',
+                'goods.in' => '充值商品非法',
+            ]
+        );
+
+        if ($validator->fails()) {
+            return $this->validatorError($validator->messages()->all(), ErrorCode::CLIENT_WRONG_PARAMS);
+        }
+
+        $user = Auth::guard('api')->user();
+        $data['goods_id'] = 1;
+        if (!isset($data['goods'])) {//默认充余额
+            $data['goods'] = order::GOODS_TYPE_COIN;
+        }
+        $data['user_id'] = $user->id;
+        if ($data['type'] == order::PAY_TYPE_ALIPAY) {
+            $result = $this->createAlipayCharge($data);
+        } else {
+            $result = $this->createWechatpayCharge($data);
+        }
+
+        if ($result === false) {
+            return $this->error(ErrorCode::ORDER_GENERATE_FAILED);
+        }
+        //log
+//        $data['amount'] = $data['number'];
+//        $this->chargeLog('Merchant', $merchant->id, $merchant->name,
+//            'balance', $data['amount'], 'balance', $data['amount'],
+//            'Merchant', $user->id, $merchant->name);
+
+        return $this->api($result);
+    }
+
+    /**
+     * @api {post} /api/pay/order_status 订单状态查询
+     * @apiDescription 订单状态查询
+     * @apiGroup User
+     * @apiPermission Passport
+     * @apiVersion 0.1.0
+     * @apiParam {int}  [goods=1]   充值商品(1:梦想币)
+     * @apiParam {int}  number      充值数量,人民币,以分表示
+     * @apiParam {int}  type        支付类型(1:支付宝,2:微信支付)
+     * @apiSuccessExample {json} Success-Response:
+     * HTTP/1.1 200 OK
+     * {
+     *     "state": true,
+     *     "code": 0,
+     *     "message": "",
+     *     "data": {
+     *         "id": 2,
+     *         "code": "ALIPAY_201610231314145719",
+     *         "transaction_id": "201610231314145719",
+     *         "user_type": 2,
+     *         "user_id": 1,
+     *         "goods_type": 1,
+     *         "price": 1,
+     *         "number": 1,
+     *         "amount": 1,
+     *         "pay_type": 1,
+     *         "status": 0,
+     *         "created_at": "2016-10-23 13:14:14",
+     *         "updated_at": "2016-10-23 13:14:14",
+     *         "orderString": "alipay_sdk=lokielse%2Fomnipay-alipay&app_id=2016091201894867&biz_content=%7B%22subject%22%3A%22%5Cu7532%5Cu8c61%5Cu8054%5Cu5408-%5Cu4f59%5Cu989d%5Cu5145%5Cu503c%22%2C%22out_trade_no%22%3A%22201610231314145719%22%2C%22total_amount%22%3A0.01%2C%22product_code%22%3A1%7D&charset=UTF-8&format=JSON&method=alipay.trade.app.pay&notify_url=http%3A%2F%2Fweb%2Fapi%2Fpay%2Falipay%2Fnotify&sign_type=RSA&timestamp=2016-10-23+13%3A14%3A14&version=1.0&sign=oxKM0qGMHLWDlMrXHIiy9%2Fk2BXJq3rC3RKdmcfFwkBJVRXvtG6cBoAYPll6VxJYOMQWeu78Ibfov%2FxIVCuN9yUfzEiokfQrzBoptc94bCQ5k0pNyJcSdgezOUKHB12P5Zmm3Hd6AAbGRDV9UCaLVz0wYkFJPrCyUv1ZfhrM%2BBqc%3D"
+     *     }
+     * }
+     * @apiErrorExample {json} Error-Response:
+     * HTTP/1.1 400 Bad Request
+     * {
+     *     "state": false,
+     *     "code": 1000,
+     *     "message": "传入参数不正确",
+     *     "data": null or []
+     * }
+     * 可能出现的错误代码:
+     * 1000    CLIENT_WRONG_PARAMS             传入参数不正确
+     */
+
+    public function orderStatus(Request $request)
+    {
+
+        $validator = Validator::make($data = $request->all(),
+            [
+                'number' => 'required|integer|min:1',
+                'type' => 'required|in:' . join(',', $pTypes),
+                'goods' => 'in:' . join(',', $gTypes),
+            ],
+            [
+                'number.required' => '请输入梦想币数量',
+                'number.integer' => '梦想币数量必须为整数',
+                'number.min' => '充值梦想币数量至少为1',
+                'type.required' => '支付类型必填',
+                'type.in' => '支付类型非法',
+                'goods.in' => '充值商品非法',
+            ]
+        );
+
+        if ($validator->fails()) {
+            return $this->validatorError($validator->messages()->all(), ErrorCode::CLIENT_WRONG_PARAMS);
+        }
+        $order = new order();
+        $order->code            = $data['code'];
+        $order->transaction_id  = $data['transaction_id'];
+        $order->user_id         = $data['user_id'];
+        $order->goods_id        = $data['goods_id'];
+        $order->price           = $data['price'];
+        $order->number          = $data['number'];
+        $order->amount          = $data['amount'];
+        $order->pay_type        = $data['pay_type'];
+        if (isset($data['ext_info'])) {
+            $order->ext_info = $data['ext_info'];
+        }
+
+        if ($order->save()) {
+            return $order->find($order->id);
+        }
+        return $this->api('');
+    }
+
+    public function orderIos(Request $request)
+    {
+
+        $validator = Validator::make($data = $request->all(),
+            [
+                'number' => 'required',
+            ],
+            [
+                'number.required' => '请输入产品ID',
+            ]
+        );
+
+        if ($validator->fails()) {
+            return $this->validatorError($validator->messages()->all(), ErrorCode::CLIENT_WRONG_PARAMS);
+        }
+//        $order = new order();
+
+        Log::info($data['number']);
+
+        $AppleProducts = order::getAllAppleProducts();
+        $coin = 0 ;
+        if(isset($AppleProducts[$data['number']])){
+            $coin = $AppleProducts[$data['number']];
+        }
+//        $order->code            = $data['code'];
+//        $order->transaction_id  = $data['transaction_id'];
+//        $order->user_id         = $data['user_id'];
+//        $order->goods_id        = $data['goods_id'];
+//        $order->price           = $data['price'];
+//        $order->number          = $data['number'];
+//        $order->amount          = $data['amount'];
+//        $order->pay_type        = $data['pay_type'];
+
+        //更新订单状态
+//        $order->status = order::STATUS_FINISHED;
+//        $order->save();
+
+        $u = Auth::guard('api')->user();
+        $u->coin += $coin;
+        $u->save();
+        //记日志
+        $_types = AccountLog::getAllType();
+        $_ops = AccountLog::getAllop();
+        $this->logAccount($_types[AccountLog::TYPE_CASH], $u->id, $u->name,$coin,
+            $_ops[AccountLog::OP_CHARGE],
+            $_types[AccountLog::TYPE_COIN], $u->id,$u->name,$coin,$data['number'],'http://miao.beiyuesi.com/base/img/apple.png');
+
+        Log::info('支付完成');
+
+        return $this->api('');
+    }
+}

+ 264 - 0
app/Http/Controllers/V1/ProductController.php

xqd
@@ -0,0 +1,264 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+use App\Models\Product;
+use App\Models\ProductType;
+use App\Models\ReportLog;
+use App\Models\UserCollect;
+use App\Models\UserLike;
+use Illuminate\Http\Request;
+
+/**
+ *
+ * 产品
+ */
+class ProductController extends Controller
+{
+    public function __construct()
+    {
+        $this->user = auth('api')->user();
+        $this->userId = $this->user ? $this->user->id : 0;
+
+        //如果用户被删除,会自动退出登录
+        if (!empty($this->user->deleted_at)) {
+            $this->user->online = 0;
+            $this->user->save();
+            auth('api')->logout();
+        }
+    }
+    /**
+     * @param Request $request
+     * @return \Illuminate\Http\JsonResponse
+     *分类数据筛选
+     */
+    public function filterTypeList(Request $request){
+      $pid = $request->input('pid');
+      $map = [];
+      $maps = [];
+      if($pid){
+          $map[] = ['pid','=',$pid];
+          $maps[] = ['filter_display_pid','=',$pid];
+      }
+      $list = ProductType::query()
+          ->where('status',1)
+          ->where($map)
+          ->orWhere($maps)
+          ->get();
+      $data = [];
+      foreach ($list as $v){
+          $data[] =[
+              'id'                  => $v['id'],
+              'icon'                => $v['icon'],
+              'zh_name'             => $v['zh_alias'] != null?$v['zh_alias']:$v['zh_name'],
+              'ko_name'             => $v['ko_alias'] != null?$v['ko_alias']:$v['ko_name'],
+              'pid'                 => $v['filter_display_pid'] > 0?$v['filter_display_pid']:$v['pid'],
+              'is_display'          => $v['is_filter_display']
+          ];
+      }
+      return $this->success($this->recursion($data,$pid?$pid:0));
+    }
+
+
+    /**
+     * @param Request $request
+     * @return \Illuminate\Http\JsonResponse
+     * 分类数据上传
+     */
+    public function uploadTypeList(Request $request){
+        $pid = $request->input('pid');
+        $map = [];
+        $maps = [];
+        if($pid){
+            $map[] = ['pid','=',$pid];
+            $maps[] = ['upload_display_pid','=',$pid];
+        }
+        $list = ProductType::query()
+            ->where('status',1)
+            ->where($map)
+            ->orWhere($maps)
+            ->get();
+        $data = [];
+        foreach ($list as $v){
+            $data[] =[
+                'id'                  => $v['id'],
+                'icon'                => $v['icon'],
+                'zh_name'             => $v['zh_alias'] != null?$v['zh_alias']:$v['zh_name'],
+                'ko_name'             => $v['ko_alias'] != null?$v['ko_alias']:$v['ko_name'],
+                'pid'                 => $v['upload_display_pid'] > 0?$v['upload_display_pid']:$v['pid'],
+                'is_display'          => $v['is_upload_display']
+            ];
+        }
+        return $this->success($this->recursion($data,$pid?$pid:0));
+    }
+
+    /**
+     * @param $list
+     * @param $pid
+     * @return array
+     * 递归处理
+     */
+    public function recursion($list = [],$pid = 0){
+        $child = [];
+        foreach ($list as $value) {
+            if($value['is_display'] != 0){
+                if ($value['pid'] == $pid ) {
+                    if($this->recursion($list, $value['id'])){
+                        // 递归调用,查找当前数据的子级
+                        $value['child'] = $this->recursion($list, $value['id']);
+                    }
+                    // 把子级数据添加进数组
+                    $child[] = $value;
+                }
+            }
+        }
+        return $child;
+    }
+
+    /**
+     * @return void
+     * 添加产品
+     */
+    public function addProduct(Request $request){
+        $params =  $request->all();
+        if(empty($params)){
+            return $this->error("数据不能为空!");
+        }
+        $params['user_id'] = $this->userId; // 用户ID
+        $res = Product::query()->create($params);
+        if(!$res){
+            return $this->error("上传失败!");
+        }
+        return $this->success();
+
+    }
+
+    /**
+     * @return void
+     * 我的上传列表
+     */
+    public function userProductList(Request $request){
+
+        $limit = $request->get('limit',10);
+        $list = Product::query()->where('status','=',1)
+            ->where('user_id','=',$this->userId)
+            ->orderByDesc('id')
+            ->paginate($limit);
+       return $this->success($this->page($list));
+    }
+
+    /**
+     * @param Request $request
+     * @return \Illuminate\Http\JsonResponse
+     * 产品列
+     */
+    public function productList(Request $request){
+        $limit = $request->get('limit',10);
+        $type = $request->get('type');
+        $query = Product::query()->with('user:id,name,nickname,avatar,company_name,company_card_color,production_project');
+        if(!empty($type)){
+            $query->whereIn('type',$type);
+        }
+        $list = $query->where('status',1)->paginate($limit);
+        return $this->success($this->page($list));
+    }
+
+    /**
+     * @return void
+     * 产品详情
+     */
+    public function productDetail(Request $request){
+
+        $data = Product::query()
+            ->with('user:id,name,nickname,avatar,company_name,company_url,production_project')
+            ->select("id","name","user_id","content","image","type")->first();
+
+       return $this->success($data);
+
+    }
+
+    /**
+     * @return void
+     * 添加收藏
+     */
+    public function addCollect(Request $request){
+        $product = Product::query()->where('id',$request->get('product_id'))->first();
+        if(!$product){
+            return $this->error("商品不存在!");
+        }
+        $collect = UserCollect::query()->where('product_id',$product->id)->where('user_id',$this->userId)->first();
+        if($collect){
+           return $this->error("您已收藏过了!");
+        }
+        $data =[
+            'product_id' => $product->id,
+            'user_id' => $this->userId,
+        ];
+        $res = UserCollect::query()->create($data);
+        if(!$res){
+            return $this->error("收藏失败!");
+        }
+        return $this->success();
+    }
+
+    /**
+     * @return void
+     * 添加喜欢
+     */
+    public function addLike(Request $request){
+        $product = Product::query()->where('id',$request->get('product_id'))->first();
+        if(!$product){
+            return $this->error("商品不存在!");
+        }
+        $collect = UserLike::query()->where('product_id',$product->id)->where('user_id',$this->userId)->first();
+        if($collect){
+            return $this->error("您已点赞过了!");
+        }
+        $data =[
+            'product_id' => $product->id,
+            'user_id' => $this->userId,
+        ];
+        $res = UserLike::query()->create($data);
+        if(!$res){
+            return $this->error("操作失败!");
+        }
+        return $this->success();
+    }
+
+    /**
+     * @return void
+     * 收藏列表
+     */
+    public function collectList(Request $request){
+        $limit = $request->get('limit',10);
+        $list = UserCollect::query()
+            ->with('product:id,name,image')
+            ->where('user_id',$this->userId)
+            ->where('is_arrange','=',0)
+            ->select("id","product_id")
+            ->paginate($limit);
+        return $this->success($this->page($list));
+    }
+
+    /**
+     * @return void
+     * 举报图片
+     */
+    public function report(Request $request){
+        $params = $request->all();
+        if(empty($params['product_id'])){
+            return $this->error("举报项不能为空!");
+        }
+        if(empty($params['report_id'])){
+            return $this->error("举报问题不能为空!");
+        }
+        $params['user_id'] = $this->userId;
+        $res = ReportLog::query()->create($params);
+        if(!$res){
+            return $this->error("举报失败!");
+        }
+        return $this->success();
+    }
+
+
+}

+ 46 - 0
app/Http/Controllers/V1/RegionController.php

xqd
@@ -0,0 +1,46 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+use App\Models\Help;
+use App\Models\Region;
+use Illuminate\Http\Request;
+use App\Models\Advertise;
+use App\Models\Setting;
+use Hamcrest\Type\IsString;
+use Illuminate\Support\Facades\Redis;
+use Illuminate\Support\Facades\Validator;
+
+class RegionController extends Controller
+{
+    //全国地区
+    public function allRegion()
+    {
+        $regionList = Redis::get('all_region');
+        if(!empty($regionList)){
+            return $this->success(json_decode($regionList, true));
+        }
+
+        $list = Region::query()
+            ->where('type', 1)
+            ->select('code', 'full_name')
+            ->get()
+            ->toArray();
+
+        foreach ($list as $key => $val) {
+            $cityList = Region::query()->where('parent_code', $val['code'])->select('code', 'full_name')->get()->toArray();
+            foreach ($cityList as $k => $v) {
+                $areaList = Region::query()->where('parent_code', $v['code'])->select('code', 'full_name')->get()->toArray();
+                $v['area_list'] = $areaList;
+                $cityList[$k] = $v;
+            }
+            $val['city_list'] = $cityList;
+            $list[$key] = $val;
+        }
+
+        Redis::setex('all_region', 24*3600, json_encode($list));
+
+        return $this->success($list);
+    }
+
+}

+ 99 - 0
app/Http/Controllers/V1/SettingsController.php

xqd
@@ -0,0 +1,99 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+use App\Models\Help;
+use App\Models\Region;
+use Illuminate\Http\Request;
+use App\Models\Advertise;
+use App\Models\Setting;
+use Hamcrest\Type\IsString;
+use Illuminate\Support\Facades\Redis;
+use Illuminate\Support\Facades\Validator;
+
+class SettingsController extends Controller
+{
+    //获取前端配置
+    public function get(Request $request)
+    {
+        $tags = $request->input('tags');
+        $key = $request->input('key');
+        $is_string = $request->input('is_string');
+
+        if($request->filled('tags')){
+          $ret = Setting::get($tags);
+        }
+        if($request->filled('tags','key')){
+          $ret = Setting::get($tags,$key);
+        }
+        if($request->filled('tags','key','is_string')){
+          $ret = Setting::get($tags,$key,$is_string);
+        }
+        return $this->output($ret);
+    }
+
+    //设置用户配置信息
+    public function set(Request $request)
+    {
+        $tags = $request->input('tags', '');
+        $key = $request->input('key', '');
+        $value = $request->input('value', '');
+
+        $validator = Validator::make($request->all(), [
+            'tags' => 'required',
+            'key' => 'required',
+            'value' => 'required',
+        ]);
+        if ($validator->fails()) {
+            return $this->error($validator->errors()->first());
+        }
+        $ret = Setting::set($tags,$key,$value);
+        return $this->output($ret);
+    }
+
+
+    /**
+     * @return void
+     * 公告|政策
+     */
+    public function noticePolicy(Request $request){
+        $data = Setting::query()->whereIn('key',['notice','privacy_policy'])->where('is_delete',0)->get();
+        return $this->success($data);
+    }
+
+    /**
+     * @return \Illuminate\Http\JsonResponse
+     * 关于我们
+     */
+    public function aboutUs(){
+        $data = Setting::query()->where('key','=','about_us')->value('value');
+        return $this->success($data);
+    }
+    /**
+     * @return \Illuminate\Http\JsonResponse
+     * 客服
+     */
+    public function customerService(){
+        $data = Setting::query()->where('key','=','customer_service')->value('value');
+        return $this->success($data);
+    }
+
+    /**
+     * @return \Illuminate\Http\JsonResponse
+     * 小程序
+     */
+    public function applet(){
+        $data = Setting::query()->where('key','=','applet')->value('value');
+        return $this->success($data);
+    }
+
+    /**
+     * @return \Illuminate\Http\JsonResponse
+     * 版本号
+     */
+    public function version(){
+        $data = Setting::query()->where('key','=','version')->value('value');
+        return $this->success($data);
+    }
+
+}

+ 64 - 0
app/Http/Controllers/V1/SmsController.php

xqd
@@ -0,0 +1,64 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+use App\Models\User;
+use App\Services\Api\ErrorMsgServive;
+use App\Services\SmsServer;
+use Illuminate\Http\Request;
+use libphonenumber\PhoneNumberUtil;
+
+class SmsController extends Controller
+{
+    //发送短信验证码
+    public function send(Request $request)
+    {
+        $checkResult = $this->checkMobile($request->mobile);
+
+        if ($checkResult['prefix'] == '-1') { //手机号不合法
+            return $this->error('手机号不合法');
+        }
+        $request->event = $request->event ?: 'login';
+        if ($request->event == "forget") {
+            if (!User::where(['mobile' => $request->mobile])->first()) {
+                return $this->error('手机号未注册');
+            }
+        }
+        $prefix = $checkResult['prefix'];
+        $result = SmsServer::send($request->mobile, $request->event, $prefix);
+        if (isset($result['error'])) {
+            return $this->error('短信发送失败');
+        }
+        $data = [
+            'smsCode' => $result['smsCode'], //注意:实际不适合把验证码返回,主要是开发方便测试,生产环境请变为 ""
+        ];
+        return $this->success($data);
+    }
+
+
+    /**
+     * @param $mobile
+     * @return array
+     * 验证手机号是否合法(支持全球手机号验证)$phoneUtil->parse($mobile, "CN"),两个参数:(要验证的手机号,国家区号)
+     * 国际区号映射关系在 vendor\giggsey\libphonenumber-for-php\src\CountryCodeToRegionCodeMap.php
+     * 可以 在 PhoneNumberUtil::getInstance() 方法中 点击 CountryCodeToRegionCodeMap::$countryCodeToRegionCodeMap 跳过去
+     */
+    public static function checkMobile($mobile)
+    {
+        $phoneUtil = PhoneNumberUtil::getInstance();
+        try {
+            $cnNumberProto = $phoneUtil->parse($mobile, "CN"); //大陆
+            $prefix = '-1';
+            if ($isValid_CN = $phoneUtil->isValidNumber($cnNumberProto)) {
+                $prefix = '86';
+            }
+            $checkResult = [
+                'prefix' => $prefix
+            ];
+            return $checkResult;
+        } catch (\libphonenumber\NumberParseException $exception) {
+            ErrorMsgServive::write($exception, request()->url());
+        }
+    }
+
+}

+ 211 - 0
app/Http/Controllers/V1/UserController.php

xqd
@@ -0,0 +1,211 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+
+use App\Models\User;
+use App\Models\UserFollow;
+use App\Services\Api\SortService;
+use App\Services\Api\UserService;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Validator;
+use App\Services\Base\ErrorCode;
+use PHPUnit\Util\Exception;
+use App\Services\SmsServer;
+
+class UserController extends Controller
+{
+    public function __construct()
+    {
+        $this->user = auth('api')->user();
+        $this->userId = $this->user ? $this->user->id : 0;
+
+        //如果用户被删除,会自动退出登录
+        if (!empty($this->user->deleted_at)) {
+            $this->user->online = 0;
+            $this->user->save();
+            auth('api')->logout();
+        }
+    }
+    /**
+     * 获取用户列表
+     */
+    public function index(Request $request)
+    {
+        $validator = Validator::make($request->all(), [
+            'nickname' => 'required',
+        ]);
+        if($validator->fails()){
+            return $this->error($validator->errors()->first(),ErrorCode::PARAMS_ERROR);
+        }
+        $search  = ['keyword'=>'1'];
+
+        $where   = ['nickname' => $request->nickname];
+        $orderby = ['id'=>'desc','created_at'=>'desc'];
+        $pagesize = 10;
+
+        $list = (new UserService())->search($search,$where,$orderby,$pagesize);
+        return $this->success($list);
+    }
+    /**
+     * 获取用户详情
+     */
+    public function show()
+    {
+        $info = (new UserService())->show($this->userId);
+        $info->follow_count = UserFollow::query()->where('user_id',$this->userId)->count();
+        return $this->success($info);
+    }
+    /**
+     * 新增用户
+     */
+    public function create(Request $request)
+    {
+        $validator = Validator::make($request->all(), [
+            'nickname' => 'required',
+            'avatar' => 'required',
+            'password' => 'required',
+            'email' => 'required',
+            'mobile' => 'required',
+        ]);
+        if($validator->fails()){
+            return $this->error($validator->errors()->first(),ErrorCode::PARAMS_ERROR);
+        }
+        $res = (new UserService())->create($request->all());
+        return $this->success($res);
+    }
+
+    /**
+     * 更新用户
+     */
+    public function upUserInfo(Request $request)
+    {
+        $validator = Validator::make($request->all(), [
+            'nickname' => 'required',
+            'name' => 'required',
+            'introduce' => 'required',
+        ]);
+        if($validator->fails()){
+            return $this->error($validator->errors()->first(),ErrorCode::PARAMS_ERROR);
+        }
+        $res = (new UserService())->update($this->userId,$request->all());
+        return $this->success($res);
+    }
+
+    /**
+     * @return void
+     * 添加关注
+     */
+    public function addFollow(Request $request){
+        $user = User::query()->where('id',$request->get('user_id'))->first();
+        if(!$user){
+            return $this->error("用户不存在!");
+        }
+        $collect = UserFollow::query()->where('user_id',$this->userId)->where('to_user_id',$user->id)->first();
+        if($collect){
+            return $this->error("您已关注过了!");
+        }
+        $data =[
+            'user_id' => $this->userId,
+            'to_user_id' => $user->id,
+        ];
+        $res = UserFollow::query()->create($data);
+        if(!$res){
+            return $this->error("操作失败!");
+        }
+        return $this->success();
+    }
+
+    /**
+     * 删除用户
+     */
+    public function destroy(Request $request,$id)
+    {
+        $res = (new UserService())->destroy($id);
+        return $this->success($res);
+    }
+
+    /**
+     * 更新用户头像
+     */
+    public function avatar(Request $request)
+    {
+        $validator = Validator::make($request->all(), [
+            'avatar' => 'required',
+        ]);
+        if($validator->fails()){
+            return $this->error($validator->errors()->first(),ErrorCode::PARAMS_ERROR);
+        }
+        $res = (new UserService())->update($this->userId,$request->all());
+        return $this->success($this->userId);
+    }
+
+    //按照首字母进行分组排序,类似手机通讯录(注意:get()后面直接 ->toArray()在数据为空的时候导致报错)
+    public function groupByInitial(Request $request)
+    {
+        $keyword = $request->input('keyword', '');
+
+        $list = User::query()
+            ->select('id', 'name', 'avatar')
+            ->when($keyword, function ($query, $keyword){
+                $query->where('name', 'like', '%'.$keyword.'%');
+            })
+            ->whereNotNull('name')
+            ->whereNull('deleted_at')
+            ->get();
+
+        if($list->isNotEmpty()){
+            $list = $list->toArray();
+            $list = SortService::getResultList($list);
+        }else{
+            $list = [];
+        }
+
+        return $this->success($list);
+    }
+
+    //绑定或解绑 手机号
+    public function bindMobile(Request $request)
+    {
+        try {
+            if(!$this->isAllowUnbound()){
+              return $this->output([],ErrorCode::NOT_ALLOW);
+            }
+            $user = User::find($this->user->id);
+            if (!empty($user->mobile)) { //要解绑
+                $user->mobile = '';
+            } else { //要绑定
+                $user->mobile = $request->mobile;
+            }
+            SmsServer::checkSmsCodeByVerifyKey($request->mobile, $request->smsCode);
+            if (!$user->save()) {
+              return $this->output([],ErrorCode::DATA_SAVE_FALSE);
+            }
+        } catch (\Exception $exception) {
+            return $this->error($exception->getMessage());
+        }
+
+        return $this->success();
+    }
+
+    //判断是否允许解绑
+    public function isAllowUnbound()
+    {
+        $user = $this->user;
+        $n = 0;
+        if(!empty($user->mobile)){
+            $n++;
+        }
+        if(!empty($user->email)){
+            $n++;
+        }
+        if(!empty($user->open_id)){
+            $n++;
+        }
+        if($n==1){
+            return false;
+        }
+        return true;
+    }
+
+}

+ 155 - 0
app/Http/Controllers/V1/UserFolderController.php

xqd
@@ -0,0 +1,155 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+use App\Models\Product;
+use App\Models\UserCollect;
+use App\Models\UserFolder;
+use App\Models\UserFolderImage;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+
+/**
+ * 用户文件夹
+ */
+class UserFolderController extends Controller
+{
+
+    public function __construct()
+    {
+        $this->user = auth('api')->user();
+        $this->userId = $this->user ? $this->user->id : 0;
+
+        //如果用户被删除,会自动退出登录
+        if (!empty($this->user->deleted_at)) {
+            $this->user->online = 0;
+            $this->user->save();
+            auth('api')->logout();
+        }
+    }
+
+    /**
+     * @return void
+     * 新建文件夹
+     */
+    public function addFolder(Request $request){
+        $params = $request->all();
+        if(empty($params['name'])){
+            return $this->error("名称不能为空!");
+        }
+        $params['user_id'] = $this->userId; // 用户ID
+        $res = UserFolder::query()->create($params);
+        if(!$res){
+            return $this->error("创建失败!");
+        }
+        return $this->success();
+    }
+
+
+    /**
+     * @return void
+     * 文件夹列表
+     */
+    public function folderList(){
+        $list = UserFolder::query()->withCount('images')->where('user_id','=',$this->userId)->get();
+        return $this->success($list);
+    }
+
+    /**
+     * @return void
+     * 文件夹详情
+     */
+    public function folderDetail(Request $request){
+        $id = $request->get('id');
+        if(!$id){
+            return $this->error("缺少参数ID!");
+        }
+        $res = UserFolder::query()->where('id',$id)->first();
+        return $this->success($res);
+    }
+
+    /**
+     * @return void
+     * 编辑文件夹
+     */
+    public function editFolder(Request $request){
+        $params = $request->all();
+        if(empty($params['id'])){
+            return $this->error("缺少参数ID");
+        }
+        if(empty($params['name'])){
+            return $this->error("标题不能为空!");
+        }
+        DB::beginTransaction();
+        try {
+            $folder = UserFolder::query()->where('id',$params['id'])->first();
+            if(!$folder){
+                throw new \Exception("数据不存在!");
+            }
+            if(!empty($params['is_del'])){
+                // 删除图片库
+                UserFolderImage::query()->where('folder_id',$params['id'])->where('user_id',$this->userId)->delete();
+                // 删除文件夹
+                $folder->delete();
+            }else{
+                $folder->update($params);
+            }
+            DB::commit();
+        }catch (\Exception $e){
+            DB::rollBack();
+            return $this->error($e->getMessage());
+        }
+       return $this->success();
+    }
+
+    /**
+     * @return void
+     * 移动文件
+     */
+    public function moveFile(Request $request){
+
+        $params = $request->all();
+        if(empty($params['folder_id'])){
+            return $this->error("缺少文件夹ID");
+        }
+//        $params['product_ids'] = [1];
+        if(empty($params['product_ids'])){
+            return $this->error("文件ID");
+        }
+        DB::beginTransaction();
+        try {
+            $product = Product::query()->whereIn('id',$params['product_ids'])->select("id","image")->get();
+            if($product){
+                foreach ($product as $v){
+                    $data = [
+                        'user_id'=>$this->userId,
+                        'folder_id'=>$params['folder_id'],
+                        'image'=>$v['image']
+                    ];
+                    UserFolderImage::query()->create($data); // 移动文件
+                    UserCollect::query()->where('product_id',$v['id'])->update(['is_arrange'=>1]); // 标识已整理的文件
+                }
+            }
+            DB::commit();
+        }catch (\Exception $e){
+            DB::rollBack();
+            return $this->error($e->getMessage());
+        }
+        return $this->success();
+    }
+
+    /**
+     * @return void
+     * 图片列表
+     */
+    public function imageList(Request $request){
+
+        $id = $request->get('folder_id');
+        $limit = $request->get('limit',10);
+        if(!$id){
+            return $this->error("缺少参数ID!");
+        }
+        $list = UserFolderImage::query()->where('folder_id','=',$id)->where('user_id',$this->userId)->paginate($limit);
+        return $this->success($this->page($list));
+    }
+
+}

+ 67 - 0
app/Http/Kernel.php

xqd
@@ -0,0 +1,67 @@
+<?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
+     */
+    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
+     */
+    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
+     */
+    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,
+    ];
+}

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

xqd
@@ -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

xqd
@@ -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
+     */
+    protected $except = [
+        //
+    ];
+}

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

xqd
@@ -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
+     */
+    protected $except = [
+        //
+    ];
+}

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

xqd
@@ -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  $next
+     * @param  string|null  ...$guards
+     * @return mixed
+     */
+    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

xqd
@@ -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
+     */
+    protected $except = [
+        'current_password',
+        'password',
+        'password_confirmation',
+    ];
+}

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

xqd
@@ -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
+     */
+    public function hosts()
+    {
+        return [
+            $this->allSubdomainsOfApplicationUrl(),
+        ];
+    }
+}

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

xqd
@@ -0,0 +1,23 @@
+<?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|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

xqd
@@ -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
+     */
+    protected $except = [
+        //
+    ];
+}

+ 95 - 0
app/Models/AccountLog.php

xqd
@@ -0,0 +1,95 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class AccountLog extends Model
+{
+    public $table = 'account_logs';
+
+    protected $fillable = [
+        'from_type',
+        'from_name',
+        'to_type',
+        'from_id',
+        'to_id',
+        'to_name',
+        'op',
+        'from_amount',
+        'to_amount',
+        'transaction_id',
+        'avatar',
+        'channel',
+        'title',
+        'dream_id',
+        'note',
+    ];
+    //交易行为定义
+    const OP_CHARGE         = 'CHARGE';
+    const OP_SUPPORT        = 'SUPPORT';
+    const OP_WITHDRAW       = 'WITHDRAW';
+    const OP_DREAM          = 'DREAM';
+
+    //货币类型定义
+    const TYPE_BALANCE      = 1;
+    const TYPE_COIN         = 2;
+    const TYPE_CASH         = 3;
+
+    //交易渠道定义
+    const CHANNEL_PLATFORM  = 'platform';
+    const CHANNEL_ALIPAY    = 'alipay';
+    const CHANNEL_WECHATPAY = 'wechatpay';
+
+//    //交易方向
+//    const DIRECTION_INC     = 1; //增加
+//    const DIRECTION_DEC     = 2; //减少
+
+    //交易行为枚举
+    private static $_op = [
+        self::OP_CHARGE         => '充值',
+        self::OP_SUPPORT        => '支持梦想',
+        self::OP_WITHDRAW       => '提现',
+        self::OP_DREAM          => '梦想结束',
+    ];
+
+    //货币类型枚举
+    private static $_type = [
+        self::TYPE_BALANCE      => '余额',
+        self::TYPE_COIN         => '梦想币',
+        self::TYPE_CASH         => '现金',
+    ];
+
+    //交易渠道枚举
+    private static $_channels = [
+        self::CHANNEL_PLATFORM  => '平台内交易',
+        self::CHANNEL_ALIPAY    => '支付宝',
+        self::CHANNEL_WECHATPAY => '微信支付',
+    ];
+
+//    // 交易流向
+//    private static $_direction = [
+//        self::DIRECTION_INC => '收入',
+//        self::DIRECTION_DEC => '支出'
+//    ];
+
+    // 获取所有操作
+    public static function getAllop() {
+        return self::$_op;
+    }
+
+    // 获取所有类型
+    public static function getAllType() {
+        return self::$_type;
+    }
+
+    //获取所有渠道
+    public static function getAllChannels() {
+        return self::$_channels;
+    }
+
+    // 获取交易流向
+    public static function getAllDirections() {
+        return self::$_direction;
+    }
+}

+ 14 - 0
app/Models/Article.php

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

+ 21 - 0
app/Models/BaseAttachment.php

xqd
@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class BaseAttachment extends Model
+{
+    //
+    /**
+     * 数据表名
+     *
+     * @var string
+     *
+     */
+    protected $table = 'base_attachments';
+    /**
+     * 主键
+     */
+    protected $primaryKey = 'id';
+}

+ 82 - 0
app/Models/BaseConfig.php

xqd
@@ -0,0 +1,82 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * Class System_Config
+ * @package App
+ */
+
+class BaseConfig extends Model
+{
+    //
+    protected $table = "base_config";
+    protected $guarded = [];
+    static $groups = [
+        'ali_config'=>'阿里云',
+        'wechat_config'=>'微信',
+        'system_config'=>'系统设置',
+        'put_config'=>'投放设置',
+        'fetch_config'=>'清运设置',
+        'cash_config'=>'提现设置',
+        'assistant_setting'=>'协管员提现设置',
+    ];
+    const Field_textarea = 0,
+          Filed_richText = 1,
+          Field_Json = 2,
+          Field_Switch = 3,
+          Field_Time = 4,
+          Field_File = 5,
+          Field_Checkbox = 6,
+          Field_Json_Array = 7;
+
+    private static $_fieldType = [
+        self::Field_textarea =>'纯文本',
+        self::Filed_richText =>'富文本',
+        self::Field_Json =>'JSON',
+        self::Field_Switch =>'开关',
+        self::Field_Time =>'时间',
+        self::Field_File =>'文件',
+        self::Field_Checkbox =>'选择框',
+        self::Field_Json_Array =>'数组JSON',
+    ];
+
+    protected static function getType(){
+        return self::$_fieldType;
+    }
+
+    /**
+     * @param String $group
+     * @param String $key
+     * @param String $default
+     * @return array|String
+     */
+    public static function get(string $group, string $key = '', string $default = "")
+    {
+        $query = self::where('group', $group);
+        if ($key) {
+            $res = $query->where('key', $key)->first(['value'])->value ?? $default;
+            return $res;
+        } else {
+            $res =  $query->get(['key', 'value']);
+            $arr = [];
+            foreach ($res as $index => $item) {
+                $arr[$item['key']] = $item['value'];
+            }
+            return $arr;
+        }
+    }
+
+    /**
+     * @param String $group
+     * @param String $key
+     * @param String $value
+     * @return int
+     */
+    public static function set(string $group, string $key, string $value)
+    {
+        return self::where([['group', $group], ['key', $key]])->update(['value' => $value]);
+    }
+}

+ 28 - 0
app/Models/BaseDistrict.php

xqd
@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Model;
+
+use Illuminate\Database\Eloquent\Model;
+
+class BaseDistrict extends Model
+{
+    //
+    protected $table = "base_district";
+    protected $guarded = [];
+
+
+    public function province()
+    {
+        return $this->belongsTo(BaseDistrict::class,'pid','id');
+    }
+
+    public function city()
+    {
+        return $this->belongsTo(BaseDistrict::class,'pid','id');
+    }
+
+//    public function communities()
+//    {
+//        return $this->hasMany(Communities::class,'area_id','id');
+//    }
+}

+ 22 - 0
app/Models/Column.php

xqd
@@ -0,0 +1,22 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Column extends Model
+{
+	use HasDateTimeFormatter;
+    protected $table = 'column';
+
+    protected $casts =[
+        'product_type_id'=>'array'
+    ];
+
+    public function product_type(){
+        return $this->hasOne(ProductType::class,'id','product_type_id');
+    }
+
+}

+ 12 - 0
app/Models/EmailCode.php

xqd
@@ -0,0 +1,12 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class EmailCode extends Model
+{
+    use HasFactory;
+
+}

+ 14 - 0
app/Models/Help.php

xqd
@@ -0,0 +1,14 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Help extends Model
+{
+    use HasFactory;
+
+    const CREATED_AT = null;
+    const UPDATED_AT = null;
+}

+ 11 - 0
app/Models/MailCode.php

xqd
@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class MailCode extends Model
+{
+    use HasFactory;
+}

+ 86 - 0
app/Models/Order.php

xqd
@@ -0,0 +1,86 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Order extends Model
+{
+    //
+    protected $table = 'order';
+    protected $primaryKey = 'id';
+
+    //用户类型定义
+//    const USER_TYPE_USER    = 1;
+
+    //用户类型枚举
+//    private static $_user_types = [
+//        self::USER_TYPE_USER    => '会员',
+//    ];
+
+    //商品类型定义
+    const GOODS_TYPE_COIN  = 1;
+//    const GOODS_TYPE_COSUME   = 3;
+
+    //商品类型枚举
+    private static $_goods_types = [
+        self::GOODS_TYPE_COIN    => '梦想币',
+//        self::GOODS_TYPE_COSUME     => '续消现金',
+    ];
+
+    //支付类型定义
+    const PAY_TYPE_ALIPAY     = 1;
+    const PAY_TYPE_WECHATPAY  = 2;
+
+    //支付类型枚举
+    private static $_pay_types = [
+        self::PAY_TYPE_ALIPAY       => '支付宝',
+        self::PAY_TYPE_WECHATPAY    => '微信支付',
+//        self::PAY_TYPE_UNIONPAY     => '银联支付',
+    ];
+
+    //苹果支付金额
+    private static $_apple_products = [
+        self::Apple_Product1      => 6,
+        self::Apple_Product2      => 6,
+        self::Apple_Product3      => 50,
+        self::Apple_Product4      => 188,
+        self::Apple_Product5      => 898,
+    ];
+
+    //苹果支付类型
+    const Apple_Product1    = 'apple10000';
+    const Apple_Product2    = 'apple10001';
+    const Apple_Product3    = 'apple102';
+    const Apple_Product4    = 'apple103';
+    const Apple_Product5    = 'apple104';
+
+    //订单状态定义
+    const STATUS_PENDING    = 0;
+    const STATUS_FINISHED   = 1;
+    const STATUS_CANCELED   = 2;
+
+    //订单状态枚举
+    private static $_status = [
+        self::STATUS_PENDING    => '待处理',
+        self::STATUS_FINISHED   => '已完成',
+        self::STATUS_CANCELED   => '已取消',
+    ];
+
+
+    public static function getAllGoodsTypes() {
+        return self::$_goods_types;
+    }
+
+    public static function getAllStatus() {
+        return self::$_status;
+    }
+
+    public static function getAllPayTypes() {
+        return self::$_pay_types;
+    }
+
+    public static function getAllAppleProducts() {
+        return self::$_apple_products;
+    }
+}

+ 32 - 0
app/Models/Product.php

xqd
@@ -0,0 +1,32 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Database\Eloquent\Model;
+
+class Product extends Model
+{
+	use HasDateTimeFormatter;
+    use SoftDeletes;
+
+    protected $table = 'product';
+
+    protected $fillable = [
+        'type',
+        'user_id',
+        'name',
+        'content',
+        'image',
+        'status'
+    ];
+
+    public function type(){
+        return $this->hasOne(ProductType::class,'id','type');
+    }
+
+    public function user(){
+        return $this->hasOne(User::class,'id','user_id');
+    }
+}

+ 81 - 0
app/Models/ProductType.php

xqd
@@ -0,0 +1,81 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Dcat\Admin\Traits\ModelTree;
+use Illuminate\Database\Eloquent\Model;
+
+class ProductType extends Model
+{
+	use HasDateTimeFormatter,ModelTree;
+    protected $table = 'product_types';
+
+    // 父级ID字段名称,默认值为 parent_id
+    protected $parentColumn = 'pid';
+    // 排序字段名称,默认值为 order
+    protected $orderColumn = 'sort';
+
+    // 标题字段名称,默认值为 title
+    protected $titleColumn = 'zh_name';
+//    public function __construct()
+//    {
+//        $lang = request()->session()->get('admin.config.lang');
+//        if($lang){
+//            dd($lang);
+//            switch ($lang){
+////            case 'en':// 英文
+////                $lang = 'en';
+////                break;
+//                case 'ko':// 韩语
+//                    $this->titleColumn = 'ko_name';
+//                    break;
+//                default:// 中文
+//                    $this->titleColumn = 'zh_name';
+//                    break;
+//            }
+//        }
+//    }
+
+    /**
+     * @param $pid
+     * @return array
+     * 获取父级ID
+     */
+    public static function level($pid = 0){
+            $list = self::query()->orderByDesc('sort')->orderByDesc('id')->pluck('pid','id');
+            return self::superior($list,$pid);
+    }
+    /**
+     * 得到当前位置父辈数组
+     * @param int
+     * @return array
+     */
+    public static function superior( $column = null, $id = 0 ){
+        $list = [];
+        foreach($column as $k=>$v){
+            if($k == $id){
+                $list[] = $k;
+                $list = array_merge(self::superior($column,$v),$list);
+            }
+        }
+        return $list;
+    }
+
+    protected $fillable =[
+        'icon',
+        'pid',
+        'level',
+        'zh_name',
+        'ko_name',
+        'sort',
+        'route_id',
+        'status',
+        'is_upload_display',
+        'is_filter_display',
+        'zh_alias',
+        'ko_alias',
+        'fill_id'
+    ];
+}

+ 11 - 0
app/Models/Region.php

xqd
@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Region extends Model
+{
+    use HasFactory;
+}

+ 20 - 0
app/Models/Report.php

xqd
@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Report extends Model
+{
+	use HasDateTimeFormatter;
+    protected $table = 'report';
+
+    protected $fillable =[
+        'title',
+        'content',
+        'sort',
+        'status'
+    ];
+}

+ 29 - 0
app/Models/ReportLog.php

xqd
@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\Model;
+
+class ReportLog extends Model
+{
+	use HasDateTimeFormatter;
+    protected $table = 'report_log';
+
+    protected $fillable = [
+        'user_id',
+        'product_id',
+        'report_id'
+    ];
+
+    public function user(){
+        return $this->hasOne(User::class,'id','user_id');
+    }
+    public function product(){
+        return $this->hasOne(Product::class,'id','product_id');
+    }
+    public function report(){
+        return $this->hasOne(Report::class,'id','report_id');
+    }
+}

+ 65 - 0
app/Models/Setting.php

xqd
@@ -0,0 +1,65 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Setting extends Model
+{
+    use HasFactory;
+
+    protected $table = 'settings';
+
+    //todo 对数据库做简单的封装 get和set(管理端会用到)  加缓存
+    /**
+     * @param String $tags
+     * @param String $key
+     * @param String $default
+     * @return array|String
+     */
+    public static function get(string $tags, string $key = '', bool $is_string = false)
+    {
+        if($tags){
+          $map[] = ['tags','=',$tags];
+        }
+        if($key){
+          $map[] = ['key','=',$key];
+        }
+        $map[] = ['is_delete','=',0];
+        if($is_string){
+          $list = self::where($map)->select('title', 'key', 'value','tags')->get();
+          $settings = [];
+          foreach($list as $key=>&$val){
+            $settings[$val['tags']][] = $val;
+          }
+        }else{
+          $list = self::where($map)->select('title', 'key', 'value','tags')->get()->toArray();
+          $settings = [];
+          foreach($list as $key=>&$val){
+            $val['value'] = json_decode($val['value']);
+            $settings[$val['tags']][] = $val;
+          }
+        }
+        return $settings;
+    }
+
+    /**
+     * @param String $tags
+     * @param String $key
+     * @param String $value
+     * @return int
+     */
+    public static function set(string $tags, string $key, string $value)
+    {
+        return self::where([['tags', $tags], ['key', $key]])->update(['value' => $value]);
+    }
+
+    public function getValueAttribute($value)
+    {
+        if(is_array($value)){
+            return $value;
+        }
+        return json_decode($value, true);
+    }
+}

+ 15 - 0
app/Models/SmsRecord.php

xqd
@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class SmsRecord extends Model
+{
+    //
+    protected $table = "sms_records";
+    protected $guarded = [];
+    protected $casts = [
+        'sms_result' => 'array',
+    ];
+}

+ 101 - 0
app/Models/User.php

xqd
@@ -0,0 +1,101 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+
+use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Foundation\Auth\User as Authenticatable;
+use Illuminate\Notifications\Notifiable;
+use PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject;
+
+class User extends Authenticatable implements JWTSubject
+{
+    use Notifiable,HasDateTimeFormatter,SoftDeletes;
+
+    /**
+     * The attributes that are mass assignable.
+     *
+     * @var array
+     */
+    protected $fillable = [
+        'account',
+        'name',
+        'email',
+        'avatar',
+        'password',
+        'mobile',
+        'status',
+        'online',
+        'lang',
+        'jpush_reg_id',
+        'last_login_ip',
+        'register_ip',
+        'last_login_time',
+        'is_counting',
+        'is_cashier',
+        'member_id',
+        'company_image',
+        'company_card_color',
+        'company_name',
+        'production_project',
+        'company_url',
+        'company_phone',
+        'other_contacts',
+        'start_time',
+        'end_time'
+    ];
+    public function memberStatus(){
+        return [1 => '一般会员', 2 => '企业会员'];
+    }
+
+    protected $appends =[
+        'member_id_text',
+    ];
+    public function getMemberIdTextAttribute()
+    {
+        $list = $this->memberStatus();
+        if(empty($this->attributes['member_id'])){
+            return null;
+        }
+        return isset($list[$this->attributes['member_id']]) ? $list[$this->attributes['member_id']] : '';
+    }
+
+    //protected $guarded = [];
+    /**
+     * The attributes that should be hidden for arrays.
+     *
+     * @var array
+     */
+    // protected $hidden = [
+    //     'password',
+    //     'remember_token',
+    // ];
+
+    public function getJWTIdentifier()
+    {
+        return $this->getKey(); // TODO: Implement getJWTIdentifier() method.
+    }
+
+    public function getJWTCustomClaims()
+    {
+        return [
+            'role' => 'user'
+        ];  // TODO: Implement getJWTCustomClaims() method.
+    }
+
+    /**
+     * 设置密码加密
+     * @param $value
+     * @return string
+     */
+    public function setPasswordAttribute($value)
+    {
+        $this->attributes['password'] = bcrypt($value);
+    }
+
+
+    public function member(){
+        return $this->hasOne(UserMember::class,'id','member_id');
+    }
+}

+ 23 - 0
app/Models/UserCollect.php

xqd
@@ -0,0 +1,23 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+use Illuminate\Database\Eloquent\Model;
+
+class UserCollect extends Model
+{
+	use HasDateTimeFormatter;
+
+    protected $table = 'user_collect';
+
+    protected $fillable = [
+        'user_id',
+        'product_id',
+        'is_arrange'
+    ];
+
+    public function product(){
+        return $this->hasOne(Product::class,'id','product_id');
+    }
+}

+ 29 - 0
app/Models/UserFolder.php

xqd
@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+use Illuminate\Database\Eloquent\Model;
+
+class UserFolder extends Model
+{
+	use HasDateTimeFormatter;
+
+    protected $table = 'user_folder';
+
+    protected $fillable = [
+        'user_id',
+        'name',
+        'is_private',
+        'is_del',
+        'images'
+    ];
+
+    protected $casts = [
+        'images'=>'array'
+    ];
+
+    public function images(){
+        return $this->hasMany(UserFolderImage::class,'folder_id','id');
+    }
+}

+ 20 - 0
app/Models/UserFolderImage.php

xqd
@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+use Illuminate\Database\Eloquent\Model;
+
+class UserFolderImage extends Model
+{
+	use HasDateTimeFormatter;
+
+    protected $table = 'user_folder_images';
+
+    protected $fillable = [
+        'user_id',
+        'folder_id',
+        'image',
+    ];
+
+}

+ 19 - 0
app/Models/UserFollow.php

xqd
@@ -0,0 +1,19 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+use Illuminate\Database\Eloquent\Model;
+
+class UserFollow extends Model
+{
+	use HasDateTimeFormatter;
+
+    protected $table = 'user_follow';
+
+    protected $fillable = [
+        'user_id',
+        'to_user_id',
+    ];
+
+}

+ 19 - 0
app/Models/UserLike.php

xqd
@@ -0,0 +1,19 @@
+<?php
+
+namespace App\Models;
+
+use Dcat\Admin\Traits\HasDateTimeFormatter;
+use Illuminate\Database\Eloquent\Model;
+
+class UserLike extends Model
+{
+	use HasDateTimeFormatter;
+
+    protected $table = 'user_like';
+
+    protected $fillable = [
+        'user_id',
+        'product_id',
+    ];
+
+}

+ 14 - 0
app/Models/UserMember.php

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

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.