Browse Source

清除缓存

qiuzijian 2 years ago
parent
commit
9c6991a8ea
100 changed files with 6587 additions and 0 deletions
  1. 15 0
      .editorconfig
  2. 44 0
      .env.example
  3. BIN
      .env.swp
  4. 5 0
      .gitattributes
  5. 16 0
      .gitignore
  6. 4 0
      .idea/encodings.xml
  7. 5 0
      .idea/inspectionProfiles/Project_Default.xml
  8. 44 0
      .idea/misc.xml
  9. 8 0
      .idea/modules.xml
  10. 132 0
      .idea/php.xml
  11. 6 0
      .idea/vcs.xml
  12. 60 0
      .idea/video_system.iml
  13. BIN
      .rnd
  14. 13 0
      .styleci.yml
  15. 346 0
      Modules/Admin/Auxiliary/View/FromAuxiliary.php
  16. 159 0
      Modules/Admin/Auxiliary/View/TableAuxiliary.php
  17. 101 0
      Modules/Admin/Auxiliary/View/TreeAuxiliary.php
  18. 0 0
      Modules/Admin/Config/.gitkeep
  19. 5 0
      Modules/Admin/Config/config.php
  20. 0 0
      Modules/Admin/Console/.gitkeep
  21. 0 0
      Modules/Admin/Database/Migrations/.gitkeep
  22. 44 0
      Modules/Admin/Database/Migrations/2021_04_15_025757_create_menus_table.php
  23. 34 0
      Modules/Admin/Database/Migrations/2022_05_19_095605_update_users_table_0519.php
  24. 0 0
      Modules/Admin/Database/Seeders/.gitkeep
  25. 382 0
      Modules/Admin/Database/Seeders/AdminDatabaseSeeder.php
  26. 0 0
      Modules/Admin/Database/factories/.gitkeep
  27. 0 0
      Modules/Admin/Entities/.gitkeep
  28. 10 0
      Modules/Admin/Entities/Menu.php
  29. 22 0
      Modules/Admin/Enum/AdminEnum.php
  30. 15 0
      Modules/Admin/Enum/UserEnum.php
  31. 0 0
      Modules/Admin/Http/Controllers/.gitkeep
  32. 46 0
      Modules/Admin/Http/Controllers/AdminController.php
  33. 83 0
      Modules/Admin/Http/Controllers/Api/TokenController.php
  34. 255 0
      Modules/Admin/Http/Controllers/BaseController.php
  35. 111 0
      Modules/Admin/Http/Controllers/LoginController.php
  36. 179 0
      Modules/Admin/Http/Controllers/MenusController.php
  37. 225 0
      Modules/Admin/Http/Controllers/UsersController.php
  38. 0 0
      Modules/Admin/Http/Middleware/.gitkeep
  39. 0 0
      Modules/Admin/Http/Requests/.gitkeep
  40. 42 0
      Modules/Admin/Http/Requests/MenusRequest.php
  41. 0 0
      Modules/Admin/Providers/.gitkeep
  42. 125 0
      Modules/Admin/Providers/AdminServiceProvider.php
  43. 69 0
      Modules/Admin/Providers/RouteServiceProvider.php
  44. 0 0
      Modules/Admin/Resources/assets/.gitkeep
  45. 0 0
      Modules/Admin/Resources/assets/js/app.js
  46. 0 0
      Modules/Admin/Resources/assets/sass/app.scss
  47. 0 0
      Modules/Admin/Resources/lang/.gitkeep
  48. 0 0
      Modules/Admin/Resources/views/.gitkeep
  49. 8 0
      Modules/Admin/Resources/views/component/breadcrumb.blade.php
  50. 25 0
      Modules/Admin/Resources/views/component/excel_table.blade.php
  51. 142 0
      Modules/Admin/Resources/views/component/icon_list.blade.php
  52. 12 0
      Modules/Admin/Resources/views/component/multi_select_option.blade.php
  53. 17 0
      Modules/Admin/Resources/views/component/side_menu.blade.php
  54. 960 0
      Modules/Admin/Resources/views/component/template_from.blade.php
  55. 387 0
      Modules/Admin/Resources/views/component/template_table_list.blade.php
  56. 35 0
      Modules/Admin/Resources/views/component/template_table_view.blade.php
  57. 37 0
      Modules/Admin/Resources/views/component/template_tree_item.blade.php
  58. 224 0
      Modules/Admin/Resources/views/component/template_tree_list.blade.php
  59. 9 0
      Modules/Admin/Resources/views/index.blade.php
  60. 20 0
      Modules/Admin/Resources/views/layouts/error.blade.php
  61. 273 0
      Modules/Admin/Resources/views/layouts/master.blade.php
  62. 168 0
      Modules/Admin/Resources/views/layouts/sub.blade.php
  63. 16 0
      Modules/Admin/Resources/views/layouts/success.blade.php
  64. 193 0
      Modules/Admin/Resources/views/login.blade.php
  65. 91 0
      Modules/Admin/Resources/views/roles.blade.php
  66. 0 0
      Modules/Admin/Routes/.gitkeep
  67. 23 0
      Modules/Admin/Routes/api.php
  68. 48 0
      Modules/Admin/Routes/web.php
  69. 57 0
      Modules/Admin/Services/FilterService.php
  70. 255 0
      Modules/Admin/Services/MenusService.php
  71. 135 0
      Modules/Admin/Services/UsersService.php
  72. 0 0
      Modules/Admin/Tests/Feature/.gitkeep
  73. 0 0
      Modules/Admin/Tests/Unit/.gitkeep
  74. 259 0
      Modules/Admin/Traits/ClassifyMethod.php
  75. 23 0
      Modules/Admin/composer.json
  76. 13 0
      Modules/Admin/module.json
  77. 17 0
      Modules/Admin/package.json
  78. 14 0
      Modules/Admin/webpack.mix.js
  79. 0 0
      Modules/Camera/Config/.gitkeep
  80. 5 0
      Modules/Camera/Config/config.php
  81. 0 0
      Modules/Camera/Console/.gitkeep
  82. 0 0
      Modules/Camera/Database/Migrations/.gitkeep
  83. 33 0
      Modules/Camera/Database/Migrations/2021_04_20_071702_create_camera_field_list.php
  84. 40 0
      Modules/Camera/Database/Migrations/2021_04_20_082221_create_camera_list_table.php
  85. 34 0
      Modules/Camera/Database/Migrations/2021_04_23_032650_update_camera_list_table_fields.php
  86. 32 0
      Modules/Camera/Database/Migrations/2021_04_26_024115_add_sort_to_camera_list_table.php
  87. 32 0
      Modules/Camera/Database/Migrations/2021_05_11_092132_add_camera_type_to_camera_list.php
  88. 34 0
      Modules/Camera/Database/Migrations/2021_05_19_070340_add_field_to_camera_list_05191503.php
  89. 32 0
      Modules/Camera/Database/Migrations/2021_08_02_074532_add_is_show_to_camera_list.php
  90. 32 0
      Modules/Camera/Database/Migrations/2021_08_05_095128_add_code_stream_to_camera_list.php
  91. 32 0
      Modules/Camera/Database/Migrations/2021_08_10_102022_add_cover_picture_to_camera_list.php
  92. 32 0
      Modules/Camera/Database/Migrations/2021_12_22_162404_add_field_to_camera_list.php
  93. 32 0
      Modules/Camera/Database/Migrations/2022_01_21_151316_add_field_to_camera_list_2021_01_21.php
  94. 40 0
      Modules/Camera/Database/Migrations/2022_07_08_153542_create_playback.php
  95. 30 0
      Modules/Camera/Database/Migrations/2022_07_19_172431_update_camera_list_table.php
  96. 30 0
      Modules/Camera/Database/Migrations/2022_07_21_180042_update_play_back_table.php
  97. 30 0
      Modules/Camera/Database/Migrations/2023_02_02_123955_update_camera_base64_table.php
  98. 0 0
      Modules/Camera/Database/Seeders/.gitkeep
  99. 21 0
      Modules/Camera/Database/Seeders/CameraDatabaseSeeder.php
  100. 0 0
      Modules/Camera/Database/factories/.gitkeep

+ 15 - 0
.editorconfig

@@ -0,0 +1,15 @@
+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]
+indent_size = 2

+ 44 - 0
.env.example

@@ -0,0 +1,44 @@
+APP_NAME=Laravel
+APP_ENV=local
+APP_KEY=
+APP_DEBUG=true
+APP_URL=http://localhost
+
+LOG_CHANNEL=stack
+
+DB_CONNECTION=mysql
+DB_HOST=127.0.0.1
+DB_PORT=3306
+DB_DATABASE=laravel
+DB_USERNAME=root
+DB_PASSWORD=
+
+BROADCAST_DRIVER=log
+CACHE_DRIVER=file
+QUEUE_CONNECTION=sync
+SESSION_DRIVER=file
+SESSION_LIFETIME=120
+
+REDIS_HOST=127.0.0.1
+REDIS_PASSWORD=null
+REDIS_PORT=6379
+
+MAIL_DRIVER=smtp
+MAIL_HOST=smtp.mailtrap.io
+MAIL_PORT=2525
+MAIL_USERNAME=null
+MAIL_PASSWORD=null
+MAIL_ENCRYPTION=null
+
+AWS_ACCESS_KEY_ID=
+AWS_SECRET_ACCESS_KEY=
+AWS_DEFAULT_REGION=us-east-1
+AWS_BUCKET=
+
+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}"

BIN
.env.swp


+ 5 - 0
.gitattributes

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

+ 16 - 0
.gitignore

@@ -0,0 +1,16 @@
+/node_modules
+/public/hot
+/public/storage
+/storage/*.key
+/vendor
+.env
+.env.backup
+.phpunit.result.cache
+Homestead.json
+Homestead.yaml
+npm-debug.log
+yarn-error.log
+/public/files
+/public/filedownload
+.idea/workspace.xml
+/app/Http/Controllers/TestsController.php

+ 4 - 0
.idea/encodings.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding" addBOMForNewFiles="with NO BOM" />
+</project>

+ 5 - 0
.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,5 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0" is_locked="false">
+    <option name="myName" value="Project Default" />
+  </profile>
+</component>

+ 44 - 0
.idea/misc.xml

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </component>
+  <component name="ProjectInspectionProfilesVisibleTreeState">
+    <entry key="Project Default">
+      <profile-state>
+        <expanded-state>
+          <State />
+          <State>
+            <id>Angular</id>
+          </State>
+          <State>
+            <id>Cucumber</id>
+          </State>
+          <State>
+            <id>Dockerfile</id>
+          </State>
+          <State>
+            <id>File Watchers</id>
+          </State>
+          <State>
+            <id>PHP</id>
+          </State>
+          <State>
+            <id>Probable bugsPHP</id>
+          </State>
+          <State>
+            <id>Type compatibilityPHP</id>
+          </State>
+          <State>
+            <id>docker-compose</id>
+          </State>
+        </expanded-state>
+        <selected-state>
+          <State>
+            <id>Angular</id>
+          </State>
+        </selected-state>
+      </profile-state>
+    </entry>
+  </component>
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/video_system.iml" filepath="$PROJECT_DIR$/.idea/video_system.iml" />
+    </modules>
+  </component>
+</project>

+ 132 - 0
.idea/php.xml

@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="PhpIncludePathManager">
+    <include_path>
+      <path value="$PROJECT_DIR$/vendor/erusev/parsedown" />
+      <path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
+      <path value="$PROJECT_DIR$/vendor/fzaninotto/faker" />
+      <path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
+      <path value="$PROJECT_DIR$/vendor/phar-io/version" />
+      <path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
+      <path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
+      <path value="$PROJECT_DIR$/vendor/symfony/mime" />
+      <path value="$PROJECT_DIR$/vendor/symfony/routing" />
+      <path value="$PROJECT_DIR$/vendor/symfony/http-client-contracts" />
+      <path value="$PROJECT_DIR$/vendor/symfony/css-selector" />
+      <path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
+      <path value="$PROJECT_DIR$/vendor/laravel/tinker" />
+      <path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
+      <path value="$PROJECT_DIR$/vendor/laravel/framework" />
+      <path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
+      <path value="$PROJECT_DIR$/vendor/symfony/debug" />
+      <path value="$PROJECT_DIR$/vendor/symfony/process" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
+      <path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
+      <path value="$PROJECT_DIR$/vendor/psr/simple-cache" />
+      <path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
+      <path value="$PROJECT_DIR$/vendor/tijsverkoyen/css-to-inline-styles" />
+      <path value="$PROJECT_DIR$/vendor/psr/log" />
+      <path value="$PROJECT_DIR$/vendor/phpunit/php-token-stream" />
+      <path value="$PROJECT_DIR$/vendor/psr/container" />
+      <path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
+      <path value="$PROJECT_DIR$/vendor/symfony/translation" />
+      <path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
+      <path value="$PROJECT_DIR$/vendor/symfony/finder" />
+      <path value="$PROJECT_DIR$/vendor/opis/closure" />
+      <path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
+      <path value="$PROJECT_DIR$/vendor/phpspec/prophecy" />
+      <path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
+      <path value="$PROJECT_DIR$/vendor/vlucas/phpdotenv" />
+      <path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
+      <path value="$PROJECT_DIR$/vendor/dragonmantank/cron-expression" />
+      <path value="$PROJECT_DIR$/vendor/nesbot/carbon" />
+      <path value="$PROJECT_DIR$/vendor/nunomaduro/collision" />
+      <path value="$PROJECT_DIR$/vendor/psy/psysh" />
+      <path value="$PROJECT_DIR$/vendor/fideloper/proxy" />
+      <path value="$PROJECT_DIR$/vendor/php-parallel-lint/php-console-highlighter" />
+      <path value="$PROJECT_DIR$/vendor/php-parallel-lint/php-console-color" />
+      <path value="$PROJECT_DIR$/vendor/paragonie/random_compat" />
+      <path value="$PROJECT_DIR$/vendor/phpoption/phpoption" />
+      <path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-docblock" />
+      <path value="$PROJECT_DIR$/vendor/dnoegel/php-xdg-base-dir" />
+      <path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-common" />
+      <path value="$PROJECT_DIR$/vendor/composer" />
+      <path value="$PROJECT_DIR$/vendor/swiftmailer/swiftmailer" />
+      <path value="$PROJECT_DIR$/vendor/mockery/mockery" />
+      <path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/environment" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
+      <path value="$PROJECT_DIR$/vendor/filp/whoops" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/diff" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/version" />
+      <path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
+      <path value="$PROJECT_DIR$/vendor/ramsey/uuid" />
+      <path value="$PROJECT_DIR$/vendor/webmozart/assert" />
+      <path value="$PROJECT_DIR$/vendor/monolog/monolog" />
+      <path value="$PROJECT_DIR$/vendor/beyondcode/laravel-dump-server" />
+      <path value="$PROJECT_DIR$/vendor/league/flysystem" />
+      <path value="$PROJECT_DIR$/vendor/hamcrest/hamcrest-php" />
+      <path value="$PROJECT_DIR$/vendor/nwidart/laravel-modules" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/cache" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/event-manager" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/deprecations" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/dbal" />
+      <path value="$PROJECT_DIR$/vendor/psr/http-message" />
+      <path value="$PROJECT_DIR$/vendor/symfony/psr-http-message-bridge" />
+      <path value="$PROJECT_DIR$/vendor/laravel/passport" />
+      <path value="$PROJECT_DIR$/vendor/psr/http-factory" />
+      <path value="$PROJECT_DIR$/vendor/league/event" />
+      <path value="$PROJECT_DIR$/vendor/league/oauth2-server" />
+      <path value="$PROJECT_DIR$/vendor/firebase/php-jwt" />
+      <path value="$PROJECT_DIR$/vendor/defuse/php-encryption" />
+      <path value="$PROJECT_DIR$/vendor/phpseclib/phpseclib" />
+      <path value="$PROJECT_DIR$/vendor/lcobucci/jwt" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle" />
+      <path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/promises" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
+      <path value="$PROJECT_DIR$/vendor/zendframework/zend-diactoros" />
+      <path value="$PROJECT_DIR$/vendor/overtrue/pinyin" />
+      <path value="$PROJECT_DIR$/vendor/box/spout" />
+      <path value="$PROJECT_DIR$/vendor/predis/predis" />
+      <path value="$PROJECT_DIR$/vendor/jacobcyl/ali-oss-storage" />
+      <path value="$PROJECT_DIR$/vendor/aliyuncs/oss-sdk-php" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
+      <path value="$PROJECT_DIR$/vendor/phpdocumentor/type-resolver" />
+      <path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-iconv" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-php72" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-php73" />
+      <path value="$PROJECT_DIR$/vendor/symfony/http-kernel" />
+      <path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
+      <path value="$PROJECT_DIR$/vendor/symfony/console" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-ctype" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" />
+      <path value="$PROJECT_DIR$/vendor/phpoffice/phpspreadsheet" />
+      <path value="$PROJECT_DIR$/vendor/psr/http-client" />
+      <path value="$PROJECT_DIR$/vendor/maennchen/zipstream-php" />
+      <path value="$PROJECT_DIR$/vendor/ezyang/htmlpurifier" />
+      <path value="$PROJECT_DIR$/vendor/myclabs/php-enum" />
+      <path value="$PROJECT_DIR$/vendor/markbaker/complex" />
+      <path value="$PROJECT_DIR$/vendor/markbaker/matrix" />
+      <path value="$PROJECT_DIR$/vendor/maatwebsite/excel" />
+    </include_path>
+  </component>
+  <component name="PhpProjectSharedConfiguration" php_language_level="7.1" />
+  <component name="PhpUnit">
+    <phpunit_settings>
+      <PhpUnitSettings configuration_file_path="$PROJECT_DIR$/phpunit.xml" custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" use_configuration_file="true" />
+    </phpunit_settings>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

+ 60 - 0
.idea/video_system.iml

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/app" isTestSource="false" packagePrefix="App\" />
+      <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="Tests\" />
+      <sourceFolder url="file://$MODULE_DIR$/Modules" isTestSource="false" packagePrefix="Modules\" />
+      <sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/aliyuncs/oss-sdk-php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/box/spout" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/defuse/php-encryption" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/cache" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/dbal" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/deprecations" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/event-manager" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/lexer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/ezyang/htmlpurifier" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/firebase/php-jwt" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/guzzle" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/promises" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/psr7" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/jacobcyl/ali-oss-storage" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/laravel/passport" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/lcobucci/jwt" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/league/event" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/league/oauth2-server" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/maatwebsite/excel" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/maennchen/zipstream-php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/markbaker/complex" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/markbaker/matrix" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/myclabs/php-enum" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/nwidart/laravel-modules" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/overtrue/pinyin" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/type-resolver" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpoffice/phpspreadsheet" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpseclib/phpseclib" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/predis/predis" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-client" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-factory" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-message" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/ralouphie/getallheaders" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-foundation" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-kernel" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-ctype" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-iconv" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-idn" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-normalizer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-mbstring" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php72" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php73" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php80" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/psr-http-message-bridge" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-dumper" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/zendframework/zend-diactoros" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

BIN
.rnd


+ 13 - 0
.styleci.yml

@@ -0,0 +1,13 @@
+php:
+  preset: laravel
+  disabled:
+    - unused_use
+  finder:
+    not-name:
+      - index.php
+      - server.php
+js:
+  finder:
+    not-name:
+      - webpack.mix.js
+css: true

+ 346 - 0
Modules/Admin/Auxiliary/View/FromAuxiliary.php

@@ -0,0 +1,346 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: maliang
+ * Date: 2019-03-30
+ * Time: 14:29
+ */
+
+namespace Modules\Admin\Auxiliary\View;
+
+
+class FromAuxiliary
+{
+    /**
+     * 提交路由
+     * @var string
+     */
+    public $path = '';
+
+    /**
+     * 表单标题
+     * @var string
+     */
+    public $title = '表单';
+
+    /**
+     * 显示数据
+     * @var
+     */
+    public $item;
+
+    /**
+     * 主视图显示字段
+     * @var
+     */
+    public $columns = [];
+
+    /**
+     * 标题宽度
+     * @var int
+     */
+    public $colWidth = 80;
+    /**
+     * 主键
+     * @var string
+     */
+    public $primaryKey = 'id';
+
+    /**
+     * 当前字段
+     * @var string
+     */
+    protected $currentColumn = '';
+
+    /**
+     * 底部显示按钮
+     * @var array
+     */
+    public $footBtns = ['goback', 'save'];
+
+    /**
+     * 是否有分割线
+     * @var bool
+     */
+    public $hasHr = false;
+
+    public function __construct($path = '', $item = '')
+    {
+        $this->item = $item;
+        $this->path = $path;
+    }
+
+    /**
+     * 设置默认值
+     * @param $default
+     * @return $this
+     */
+    public function default($default)
+    {
+        $this->columns[$this->currentColumn]['default'] = $default;
+        return $this;
+    }
+
+    /**
+     * 设置提示语
+     * @param $placeholder
+     * @return $this
+     */
+    public function placeholder($placeholder)
+    {
+        $this->columns[$this->currentColumn]['placeholder'] = $placeholder;
+        return $this;
+    }
+
+    public function text($varName, $label, $default = '')
+    {
+        $arguments = [$varName, $label, $default, ''];
+        return $this->method('text', $arguments);
+    }
+
+    public function input($varName, $label, $default = '', $placeholder = '')
+    {
+        $arguments = [$varName, $label, $default, $placeholder];
+        return $this->method('input', $arguments);
+    }
+
+    public function password($varName, $label, $default = '', $placeholder = '')
+    {
+        $arguments = [$varName, $label, $default, $placeholder];
+        return $this->method('password', $arguments);
+    }
+
+    public function textarea($varName, $label, $default = '', $placeholder = '')
+    {
+        $arguments = [$varName, $label, $default, $placeholder];
+        return $this->method('textarea', $arguments);
+    }
+
+    public function icon($varName, $label, $default = '', $placeholder = '')
+    {
+        $arguments = [$varName, $label, $default, $placeholder];
+        return $this->method('icon', $arguments);
+    }
+
+    public function date($varName, $label, $default = '', $placeholder = '')
+    {
+        $arguments = [$varName, $label, $default, $placeholder];
+        return $this->method('date', $arguments);
+    }
+
+    public function dateMonth($varName, $label, $default = '', $placeholder = '')
+    {
+        $arguments = [$varName, $label, $default, $placeholder];
+        return $this->method('dateMonth', $arguments);
+    }
+
+    public function dateYear($varName, $label, $default = '', $placeholder = '')
+    {
+        $arguments = [$varName, $label, $default, $placeholder];
+        return $this->method('dateYear', $arguments);
+    }
+
+    public function dateTime($varName, $label, $default = '', $placeholder = '')
+    {
+        $arguments = [$varName, $label, $default, $placeholder];
+        return $this->method('dateTime', $arguments);
+    }
+
+    public function time($varName, $label, $default = '', $placeholder = '')
+    {
+        $arguments = [$varName, $label, $default, $placeholder];
+        return $this->method('time', $arguments);
+    }
+
+    public function radio($varName, $label, $options, $default = '')
+    {
+        $arguments = [$varName, $label, $options, $default];
+        return $this->method('radio', $arguments);
+    }
+
+    public function checkbox($varName, $label, $options, $default = '')
+    {
+        $arguments = [$varName, $label, $options, $default];
+        return $this->method('checkbox', $arguments);
+    }
+
+    public function select($varName, $label, $options, $default = '')
+    {
+        $arguments = [$varName, $label, $options, $default];
+        return $this->method('select', $arguments);
+    }
+
+    public function xselect($varName, $label, $options, $default = '')
+    {
+        $arguments = [$varName, $label, $options, $default];
+        return $this->method('xselect', $arguments);
+    }
+
+    public function sselect($varName, $label, $options, $default = '')
+    {
+        $arguments = [$varName, $label, $options, $default];
+        return $this->method('sselect', $arguments);
+    }
+
+    public function mselect($varName, $label, $options, $default = '')
+    {
+        $arguments = [$varName, $label, $options, $default];
+        return $this->method('mselect', $arguments);
+    }
+
+    public function tselect($varName, $label, $options, $default = '')
+    {
+        $arguments = [$varName, $label, $options, $default];
+        return $this->method('tselect', $arguments);
+    }
+
+    public function trselect($varName, $label, $options, $default = '')
+    {
+        $arguments = [$varName, $label, $options, $default];
+        return $this->method('trselect', $arguments);
+    }
+
+    public function trmselect($varName, $label, $options, $default = '')
+    {
+        $arguments = [$varName, $label, $options, $default];
+        return $this->method('trmselect', $arguments);
+    }
+
+    public function tree_select($varName, $label, $options, $default = '', $isShowNull = true)
+    {
+        $arguments = [$varName, $label, $options, $default, $isShowNull];
+        return $this->method('tree_select', $arguments);
+    }
+
+    public function uploadImg($varName, $label, $uploadURLPath, $default = '')
+    {
+        $arguments = [$varName, $label, $uploadURLPath, $default];
+        return $this->method('uploadImg', $arguments);
+    }
+
+    public function uploadFile($varName, $label, $uploadURLPath)
+    {
+        $arguments = [$varName, $label, $uploadURLPath, ''];
+        return $this->method('uploadFile', $arguments);
+    }
+
+    public function uploadImgs($varName, $label, $uploadURLPath, $default = '')
+    {
+        $arguments = [$varName, $label, $uploadURLPath, $default];
+        return $this->method('uploadImgs', $arguments);
+    }
+
+    public function uploadFiles($varName, $label, $uploadURLPath, $default = '')
+    {
+        $arguments = [$varName, $label, $uploadURLPath, $default];
+        return $this->method('uploadFiles', $arguments);
+    }
+
+    public function hidden($varName, $value, $default = '')
+    {
+        $arguments = [$varName, $value, $default];
+        return $this->method('hidden', $arguments);
+    }
+
+    public function editor($varName, $label, $default = '', $uploadURLPath = '')
+    {
+        $arguments = [$varName, $label, $uploadURLPath, $default];
+        return $this->method('editor', $arguments);
+    }
+
+    public function includeBlock($varName, $label, $itemValue, $path)
+    {
+        $arguments = [$varName, $label, $itemValue, $path];
+        return $this->method('includeBlock', $arguments);
+    }
+
+    /**
+     * 调用方法
+     * @param $method
+     * @param $arguments
+     * @return FromAuxiliary
+     */
+    protected function method($method, $arguments)
+    {
+        $this->columns[$arguments[0]]['type'] = $method;
+        /**
+         * $arguments[0]  $varName
+         * $arguments[1]  $label
+         * $arguments[2]  $default = ''
+         * $arguments[3]  $placeholder = ''
+         */
+        if (in_array($method, ['text', 'input', 'password', 'textarea', 'icon', 'date', 'dateMonth', 'dateYear', 'dateTime', 'time', 'hidden'])) {
+            $var = $this->columns[$arguments[0]]['placeholder'] = $arguments[3] ?? null;
+            return $this->baseColumn($arguments[0], $arguments[1], $arguments[2] ?? '');
+        }
+
+        /**
+         * $arguments[0]  $varName
+         * $arguments[1]  $label
+         * $arguments[2]  $uploadURLPath
+         * $arguments[3]  $default = ''
+         */
+        if (in_array($method, ['uploadImg', 'uploadFile', 'uploadImgs', 'uploadFiles', 'editor'])) {
+            $this->columns[$arguments[0]]['uploadURLPath'] = $arguments[2] ?? null;
+            return $this->baseColumn($arguments[0], $arguments[1], $arguments[3] ?? '');
+        }
+
+        /**
+         * $arguments[0]  $varName
+         * $arguments[1]  $label
+         * $arguments[2]  $options
+         * $arguments[3]  $default = ''
+         */
+        if (in_array($method, ['radio', 'checkbox', 'trselect', 'trmselect', 'tselect', 'xselect', 'sselect', 'mselect', 'select'])) {
+            $this->columns[$arguments[0]]['options'] = $arguments[2] ?? [];
+            return $this->baseColumn($arguments[0], $arguments[1], $arguments[3] ?? '');
+        }
+
+        /**
+         * $arguments[0]  $varName
+         * $arguments[1]  $label
+         * $arguments[2]  $options
+         * $arguments[3]  $default = ''
+         * $arguments[4]  $isShow = ''
+         */
+        if (in_array($method, ['tree_select'])) {
+            $this->columns[$arguments[0]]['options'] = $arguments[2] ?? [];
+            $col                                     = $this->treeSelectColumn($arguments[0], $arguments[1], $arguments[3] ?? '', $arguments[4]);
+            return $col;
+        }
+
+        /**
+         * $arguments[0]  $varName
+         * $arguments[1]  $label
+         * $arguments[2]  $itemValue
+         * $arguments[3]  $default = ''
+         */
+        if (in_array($method, ['includeBlock'])) {
+            $this->columns[$arguments[0]]['itemValue'] = $arguments[2] ?? [];
+            $this->columns[$arguments[0]]['path']      = $arguments[3] ?? '';
+            return $this->baseColumn($arguments[0], $arguments[1], '');
+        }
+
+
+    }
+
+    protected function baseColumn($varName, $label, $default = '')
+    {
+        $this->columns[$varName]['value']   = $this->item[$varName] ?? '';
+        $this->columns[$varName]['label']   = $label;
+        $this->columns[$varName]['default'] = $default ?? '';
+        $this->currentColumn                = $varName;
+        return $this;
+    }
+
+    protected function treeSelectColumn($varName, $label, $default = '', $isShowNull = true)
+    {
+        $this->columns[$varName]['value']      = $this->item[$varName] ?? '';
+        $this->columns[$varName]['label']      = $label;
+        $this->columns[$varName]['default']    = $default ?? '';
+        $this->columns[$varName]['isShowNull'] = $isShowNull ?? true;
+        $this->currentColumn                   = $varName;
+        return $this;
+    }
+
+}

+ 159 - 0
Modules/Admin/Auxiliary/View/TableAuxiliary.php

@@ -0,0 +1,159 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: maliang
+ * Date: 2019-03-30
+ * Time: 21:13
+ */
+
+namespace Modules\Admin\Auxiliary\View;
+
+
+use Closure;
+
+class TableAuxiliary
+{
+    /**
+     * 增删查改前缀路由
+     * @var string
+     */
+    public $path = '';
+
+    /**
+     * 标题
+     * @var string
+     */
+    public $title = '';
+    /**
+     * 显示数据
+     * @var
+     */
+    public $items;
+
+    /**
+     * 主键
+     * @var string
+     */
+    public $primaryKey = 'id';
+
+    /**
+     * 主视图显示字段
+     * @var
+     */
+    public $columns = [];
+
+    /**
+     * 搜索字段
+     * @var array
+     */
+    public $searchColumns = [];
+
+    /**
+     * 个别不显示操作按钮
+     * 例如
+     * ['name' => 'title', 'value' => ['admin']]
+     * 显示端 结果为 true 则不显示
+     * in_array($item['title'], ['admin']);
+     * item
+     * @var array
+     */
+    public $displayActions = ['name' => 0, 'value' => [1]];
+
+    /**
+     * 每行的自定义按钮
+     * $displayActionOthers = [
+     *      [
+     *          'name' => '撤销',
+     *          'path' => 'order/list/check',
+     *          'class' => 'layui-btn-normal',
+     *          'isShow' => function($item) {},
+     *          'isJump' => 1,
+     *      ]
+     * ];
+     * @var null
+     */
+    public $displayActionOthers = null;
+
+    /**
+     * 头部的自定义按钮
+     * $displayActionOthers = [
+     *      [
+     *          'name' => '撤销',
+     *          'path' => 'order/list/check',
+     *          'class' => 'layui-btn-normal',
+     *          'isShow' => function($item) {},
+     *          'isJump' => 1,
+     *      ]
+     * ];
+     * @var null
+     */
+    public $topActionOthers = null;
+
+    /**
+     * 顶部操作按钮
+     * @var array
+     */
+    public $topActions = ['add'];
+
+    /**
+     * 显示的操作按钮
+     * @var array
+     */
+    public $actionBtns          = ['view', 'edit', 'del'];
+    public $actionBtnsAttribute = ['view' => '', 'edit' => '', 'del' => ''];
+
+    /**
+     * 当前字段
+     * @var string
+     */
+    protected $currentColumn = '';
+
+    public function __construct($path = '', $items = '')
+    {
+        $this->items = $items;
+        $this->path  = $path;
+    }
+
+    /**
+     * 显示字段
+     * @param              $varName
+     * @param string       $showName
+     * @param Closure|null $callback
+     * @return $this
+     */
+    public function column($varName, $showName = '', Closure $callback = null)
+    {
+        $this->columns[$varName]['name'] = $showName;
+        $this->currentColumn             = $varName;  // 记录当前字段
+        if (isset($callback)) {
+            $this->display($callback);
+        }
+        return $this;
+    }
+
+    /**
+     * 搜索字段
+     * @param              $varName
+     * @param string       $showName
+     * @param Closure|null $callback
+     * @return $this
+     */
+    public function search($type, $varName, $label = '', $assist = [])
+    {
+        $this->searchColumns[$varName]['type']   = $type;
+        $this->searchColumns[$varName]['label']  = $label;
+        $this->searchColumns[$varName]['assist'] = $assist;
+        return $this;
+    }
+
+    /**
+     * 处理字段结果
+     * @param Closure $callback
+     * @return $this
+     */
+    public function display(Closure $callback)
+    {
+        $this->columns[$this->currentColumn]['value'] = $callback;
+        return $this;
+    }
+}

+ 101 - 0
Modules/Admin/Auxiliary/View/TreeAuxiliary.php

@@ -0,0 +1,101 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: maliang
+ * Date: 2019-03-30
+ * Time: 10:00
+ */
+
+namespace Modules\Admin\Auxiliary\View;
+
+
+use Closure;
+
+class TreeAuxiliary
+{
+    /**
+     * 增删查改前缀路由
+     * @var string
+     */
+    public $path = '';
+
+    /**
+     * 显示数据
+     * @var
+     */
+    public $items;
+
+    /**
+     * 主视图显示字段
+     * @var
+     */
+    public $columns = [];
+
+    /**
+     * 顶部操作按钮
+     * @var array
+     */
+    public $topActions = [];
+
+    /**
+     * 头部自定义按钮
+     * $displayActionOthers = [
+     *      [
+     *          'name' => '撤销',
+     *          'path' => 'order/list/check',
+     *          'class' => 'layui-btn-normal',
+     *          'isShow' => function($item) {},
+     *          'isJump' => 1,
+     *      ]
+     * ];
+     * @var null
+     */
+    public $displayActionOthers = null;
+
+    /**
+     * 显示操作按钮定义
+     * @var array
+     */
+    public $actionBtns = ['edit', 'del'];
+
+    /**
+     * 当前字段
+     * @var string
+     */
+    protected $currentColumn = '';
+
+    public function __construct($path = '', $items = '')
+    {
+        $this->items = $items;
+        $this->path  = $path;
+    }
+
+    /**
+     * 显示字段
+     * @param              $varName
+     * @param string       $showName
+     * @param Closure|null $callback
+     * @return $this
+     */
+    public function column($varName, $showName = '', Closure $callback = null)
+    {
+        $this->columns[$varName]['name'] = $showName;
+        $this->currentColumn             = $varName;  // 记录当前字段
+        if (isset($callback)) {
+            $this->display($callback);
+        }
+        return $this;
+    }
+
+    /**
+     * 处理字段结果
+     * @param Closure $callback
+     * @return $this
+     */
+    public function display(Closure $callback)
+    {
+        $this->columns[$this->currentColumn]['value'] = $callback;
+        return $this;
+    }
+
+}

+ 0 - 0
Modules/Admin/Config/.gitkeep


+ 5 - 0
Modules/Admin/Config/config.php

@@ -0,0 +1,5 @@
+<?php
+
+return [
+    'name' => 'Admin'
+];

+ 0 - 0
Modules/Admin/Console/.gitkeep


+ 0 - 0
Modules/Admin/Database/Migrations/.gitkeep


+ 44 - 0
Modules/Admin/Database/Migrations/2021_04_15_025757_create_menus_table.php

@@ -0,0 +1,44 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class CreateMenusTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('menus', function (Blueprint $table) {
+            $table->bigIncrements('id')->comment('后台菜单表');
+            $table->integer('parent_id')->default(0)->comment('父级id');
+            $table->string('icon')->comment('图标');
+            $table->string('title')->comment('栏目名称');
+            $table->string('slug')->nullable()->comment('标识');
+            $table->string('category')->nullable()->comment('分类');
+            $table->string('path')->comment('路由');
+            $table->integer('sort')->default(10)->comment('排序');
+            $table->integer('tier')->default(1)->comment('层级');
+            $table->char('show', 1)->default(1)->comment('是否显示');
+            $table->char('can_del', 1)->default(1)->comment('是否可以删除');
+            $table->string('degree')->nullable()->comment('菜单关联');
+            $table->text('thumb')->nullable()->comment('缩略图');
+            $table->timestamps();
+            $table->softDeletes();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('menus');
+    }
+}

+ 34 - 0
Modules/Admin/Database/Migrations/2022_05_19_095605_update_users_table_0519.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class UpdateUsersTable0519 extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('users', function (Blueprint $table) {
+            if(!Schema::hasColumn('users','mine_role')) {
+                $table->string('mine_role')->nullable()->comment('区域权限');
+            }
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('users', function (Blueprint $table) {
+            $table->dropColumn('mine_role');
+        });
+    }
+}

+ 0 - 0
Modules/Admin/Database/Seeders/.gitkeep


+ 382 - 0
Modules/Admin/Database/Seeders/AdminDatabaseSeeder.php

@@ -0,0 +1,382 @@
+<?php
+
+namespace Modules\Admin\Database\Seeders;
+
+use Illuminate\Database\Seeder;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Facades\Log;
+use Modules\Admin\Services\MenusService;
+
+class AdminDatabaseSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        $menus = [
+            array (
+                'icon' => 'username',
+                'title' => '用户管理',
+                'slug' => 'adminUsers',
+                'path' => '/admin/users',
+                'sort' => 10,
+                'show' => '1',
+                'child' =>
+                    array (
+                        0 =>
+                            array (
+                                'icon' => 'user',
+                                'title' => '用户列表',
+                                'slug' => 'adminUsersList',
+                                'path' => '/admin/users/list',
+                                'sort' => 10,
+                                'show' => '1',
+                                'child' =>
+                                    array (
+                                        0 =>
+                                            array (
+                                                'icon' => 'add-1',
+                                                'title' => '添加用户',
+                                                'slug' => 'adminUsersListAdd',
+                                                'path' => '/admin/users/list/add',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        1 =>
+                                            array (
+                                                'icon' => 'search',
+                                                'title' => '查看用户',
+                                                'slug' => 'adminUsersListView',
+                                                'path' => '/admin/users/list/view',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        2 =>
+                                            array (
+                                                'icon' => 'edit',
+                                                'title' => '编辑用户',
+                                                'slug' => 'adminUsersListEdit',
+                                                'path' => '/admin/users/list/edit',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        3 =>
+                                            array (
+                                                'icon' => 'close',
+                                                'title' => '删除用户',
+                                                'slug' => 'adminUsersListDel',
+                                                'path' => '/admin/users/list/del',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        4 =>
+                                            array (
+                                                'icon' => 'password',
+                                                'title' => '重置密码',
+                                                'slug' => 'adminUsersListResetpassword',
+                                                'path' => '/admin/users/list/resetpassword',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                    ),
+                            ),
+                    ),
+            ),
+            array (
+                'icon' => 'app',
+                'title' => '矿区管理',
+                'slug' => 'adminMine',
+                'path' => '/admin/mine',
+                'sort' => 10,
+                'show' => '1',
+                'child' =>
+                    array (
+                        0 =>
+                            array (
+                                'icon' => 'list',
+                                'title' => '矿区列表',
+                                'slug' => 'adminMineList',
+                                'path' => '/admin/mine/list',
+                                'sort' => 10,
+                                'show' => '1',
+                                'child' =>
+                                    array (
+                                        0 =>
+                                            array (
+                                                'icon' => 'add-1',
+                                                'title' => '添加矿区',
+                                                'slug' => 'adminMineAdd',
+                                                'path' => '/admin/mine/add',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        1 =>
+                                            array (
+                                                'icon' => 'edit',
+                                                'title' => '修改矿区',
+                                                'slug' => 'adminMineEdit',
+                                                'path' => '/admin/mine/edit',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                    ),
+                            ),
+                        1 =>
+                            array (
+                                'icon' => 'tabs',
+                                'title' => '矿区区域列表',
+                                'slug' => 'adminSurfaceList',
+                                'path' => '/admin/surface/list',
+                                'sort' => 10,
+                                'show' => '1',
+                                'child' =>
+                                    array (
+                                        0 =>
+                                            array (
+                                                'icon' => 'add-1',
+                                                'title' => '添加区域',
+                                                'slug' => 'adminSurfaceAdd',
+                                                'path' => '/admin/surface/add',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        1 =>
+                                            array (
+                                                'icon' => 'search',
+                                                'title' => '查看区域',
+                                                'slug' => 'adminSurfaceView',
+                                                'path' => '/admin/surface/view',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        2 =>
+                                            array (
+                                                'icon' => 'edit',
+                                                'title' => '编辑区域',
+                                                'slug' => 'adminSurfaceEdit',
+                                                'path' => '/admin/surface/edit',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        3 =>
+                                            array (
+                                                'icon' => 'close',
+                                                'title' => '删除区域',
+                                                'slug' => 'adminSurfaceDel',
+                                                'path' => '/admin/surface/del',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                    ),
+                            ),
+                    ),
+            ),
+            array (
+                'icon' => 'video',
+                'title' => '摄像头管理',
+                'slug' => 'adminCamera',
+                'path' => '/admin/camera',
+                'sort' => 10,
+                'show' => '1',
+                'child' =>
+                    array (
+                        0 =>
+                            array (
+                                'icon' => 'list',
+                                'title' => '摄像头列表',
+                                'slug' => 'adminCameraList',
+                                'path' => '/admin/camera/list',
+                                'sort' => 10,
+                                'show' => '1',
+                                'child' =>
+                                    array (
+                                        0 =>
+                                            array (
+                                                'icon' => 'add-1',
+                                                'title' => '添加记录',
+                                                'slug' => 'adminCameraListAdd',
+                                                'path' => '/admin/camera/list/add',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        1 =>
+                                            array (
+                                                'icon' => 'edit',
+                                                'title' => '编辑记录',
+                                                'slug' => 'adminCameraListEdit',
+                                                'path' => '/admin/camera/list/edit',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        2 =>
+                                            array (
+                                                'icon' => 'search',
+                                                'title' => '查看记录',
+                                                'slug' => 'adminCameraListView',
+                                                'path' => '/admin/camera/list/view',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        3 =>
+                                            array (
+                                                'icon' => 'close',
+                                                'title' => '删除记录',
+                                                'slug' => 'adminCameraListDel',
+                                                'path' => '/admin/camera/list/del',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        4 =>
+                                            array (
+                                                'icon' => 'upload-drag',
+                                                'title' => '导入记录',
+                                                'slug' => 'adminCameraListImport',
+                                                'path' => '/admin/camera/list/import',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                        5 =>
+                                            array (
+                                                'icon' => 'download-circle',
+                                                'title' => '下载导入模板',
+                                                'slug' => 'adminCameraListImportTemplate',
+                                                'path' => '/admin/camera/list/importTemplate',
+                                                'sort' => 10,
+                                                'show' => '0',
+                                                'child' =>
+                                                    array (
+                                                    ),
+                                            ),
+                                    ),
+                            ),
+                    ),
+            ),
+            array (
+                'icon' => 'set-sm',
+                'title' => '后台配置',
+                'slug' => 'adminSetting',
+                'path' => '/admin/setting',
+                'sort' => 5,
+                'show' => '1',
+                'child' =>
+                    array (
+                        0 =>
+                            array (
+                                'icon' => 'table',
+                                'title' => '菜单设置',
+                                'slug' => 'adminSettingMenus',
+                                'path' => '/admin/menus/list',
+                                'sort' => 10,
+                                'show' => '1',
+                                'child' =>
+                                    array (
+                                    ),
+                            ),
+                        1 =>
+                            array (
+                                'icon' => 'add-1',
+                                'title' => '添加菜单',
+                                'slug' => 'adminSettingMenusAdd',
+                                'path' => '/admin/menus/add',
+                                'sort' => 10,
+                                'show' => '0',
+                                'child' =>
+                                    array (
+                                    ),
+                            ),
+                        2 =>
+                            array (
+                                'icon' => 'edit',
+                                'title' => '编辑菜单',
+                                'slug' => 'adminSettingMenusEdit',
+                                'path' => '/admin/menus/edit',
+                                'sort' => 10,
+                                'show' => '0',
+                                'child' =>
+                                    array (
+                                    ),
+                            ),
+                        3 =>
+                            array (
+                                'icon' => 'close',
+                                'title' => '删除菜单',
+                                'slug' => 'adminSettingMenusDel',
+                                'path' => '/admin/menus/del',
+                                'sort' => 10,
+                                'show' => '0',
+                                'child' =>
+                                    array (
+                                    ),
+                            ),
+                    ),
+            ),
+        ];
+
+        $this->addMenu($menus);
+    }
+
+    public function addMenu($menuList, $parentId = 0)
+    {
+        $menuService = new MenusService();
+        foreach ($menuList as $menu) {
+            $menu['parent_id'] = $parentId;
+            $_menu             = $menu;
+            unset($_menu['child']);
+            $menu_parent = $menuService->addMenu($_menu, 'slug');
+            if (count($menu['child']) > 0) {
+                $this->addMenu($menu['child'], $menu_parent['id']);
+            }
+        }
+    }
+}

+ 0 - 0
Modules/Admin/Database/factories/.gitkeep


+ 0 - 0
Modules/Admin/Entities/.gitkeep


+ 10 - 0
Modules/Admin/Entities/Menu.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace Modules\Admin\Entities;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Menu extends Model
+{
+    protected $fillable = ['parent_id', 'icon', 'title', 'slug', 'category', 'path', 'sort', 'tier', 'show', 'can_del', 'thumb'];
+}

+ 22 - 0
Modules/Admin/Enum/AdminEnum.php

@@ -0,0 +1,22 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: qiuzijian
+ * Date: 2021-04-20
+ * Time: 15:37
+ */
+
+namespace Modules\Admin\Enum;
+
+class AdminEnum
+{
+    //后台状态返回
+    const RETURN_SUCCESS       = '成功';
+    const USER_ALREADY_EXIST   = '该用户编码已存在';
+    const DATABASE_ERROR       = '数据库异常失败';
+    const USER_NOT_EXIST       = '后台用户不存在';
+    const RECORD_ALREADY_EXIST = '该记录已存在';
+    const RECORD_NOT_EXIST     = '记录不存在';
+    const MINE_NOT_EXIST       = '所传矿井不存在';
+    const MINE_AREA_NOT_EXIST  = '所传区域不存在';
+}

+ 15 - 0
Modules/Admin/Enum/UserEnum.php

@@ -0,0 +1,15 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: qiuzijian
+ * Date: 2021-04-16
+ * Time: 15:21
+ */
+
+namespace Modules\Admin\Enum;
+
+class UserEnum
+{
+    //后台用户默认密码
+    const ADMIN_USER_DETAULT_PASSWORD = 'Zhks123456+';
+}

+ 0 - 0
Modules/Admin/Http/Controllers/.gitkeep


+ 46 - 0
Modules/Admin/Http/Controllers/AdminController.php

@@ -0,0 +1,46 @@
+<?php
+
+namespace Modules\Admin\Http\Controllers;
+
+use Illuminate\Contracts\Support\Renderable;
+use Illuminate\Http\Request;
+use Illuminate\Routing\Controller;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\View;
+use Modules\Admin\Services\MenusService;
+
+class AdminController extends Controller
+{
+    public function __construct()
+    {
+
+    }
+
+    /**
+     * Display a listing of the resource.
+     * @return Renderable
+     */
+    public function index(Request $request)
+    {
+        $user = Auth::guard('web')->user();
+
+        // 获取并共享可见菜单信息
+        $menus = new MenusService();
+        $menus = $menus->getMenusList(1);
+//        if (!$request->user()->hasRole('superAdmin')) {
+//            $menus = $this->filterMenu($menus, $request->user()->getAllPermissions()->pluck('name')->all());
+//        }
+
+        $data = [
+            'user'  => $user,
+            'menus' => $menus,
+        ];
+
+        return view('admin::index', $data);
+    }
+
+    public function welcomeView()
+    {
+
+    }
+}

+ 83 - 0
Modules/Admin/Http/Controllers/Api/TokenController.php

@@ -0,0 +1,83 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: qiuzijian
+ * Date: 4/1/22
+ * Time: 6:29 PM
+ */
+
+namespace Modules\Admin\Http\Controllers\Api;
+
+use App\Enum\ApiEnum;
+use App\Http\Controllers\Controller;
+use Illuminate\Http\Request;
+use Modules\Admin\Entities\User;
+use Modules\Admin\Http\Requests\TokenRequest;
+use Modules\Staff\Entities\Staff;
+use Symfony\Component\HttpFoundation\Response;
+
+class TokenController extends Controller
+{
+    public function token(Request $request)
+    {
+        $result['status'] = true;
+        $result['msg']    = ApiEnum::RETURN_SUCCESS;
+        $result['data']   = [];
+
+        $username = $request->input('username');
+
+        $user = \App\User::where('staff_num', $username)->first();
+        if (!$user) {
+            return $this->error(1001, '用户不存在');
+        }
+
+        $result = $this->issueToken($request, 'password');
+        if ($result->getStatusCode() == 401) {
+            return $this->error(1002, '密码错误');
+        }
+
+        $data = json_decode($result->getContent(), true);
+
+        $result = [
+            'code'    => 0,
+            'message' => 'SUCCESS',
+            'data'    => $data
+        ];
+
+        return response()->json($result);
+    }
+
+    protected function error($code = 1, $msg = '')
+    {
+        return [
+            'code'    => $code,
+            'message' => $msg,
+        ];
+    }
+
+    /**
+     * Passport 接口请求
+     * @param Request $request
+     * @param         $grant_type
+     * @param string  $provider
+     * @param string  $scope
+     * @return Response
+     */
+    protected function issueToken(Request $request, $grant_type, $provider = 'users', $scope = '*'): Response
+    {
+        $client = config('passport.password');
+        $params = [
+            'grant_type'    => $grant_type,
+            'client_id'     => $client['client_id'],
+            'client_secret' => $client['client_secret'],
+            'username'      => $request->username ?: $request->email,
+            'password'      => $request->password,
+            'provider'      => $provider,
+            'scope'         => $scope,
+        ];
+
+        $proxy = $request::create('oauth/token', 'POST');
+        $proxy->request->add($params);
+        return app()->handle($proxy);
+    }
+}

+ 255 - 0
Modules/Admin/Http/Controllers/BaseController.php

@@ -0,0 +1,255 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: qiuzijian
+ * Date: 2021-04-15
+ * Time: 11:29
+ */
+
+namespace Modules\Admin\Http\Controllers;
+
+use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
+use Illuminate\Foundation\Bus\DispatchesJobs;
+use Illuminate\Foundation\Validation\ValidatesRequests;
+use Illuminate\Routing\Controller;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Request;
+use Illuminate\Support\Facades\View;
+use Modules\Admin\Auxiliary\View\FromAuxiliary;
+use Modules\Admin\Auxiliary\View\TableAuxiliary;
+use Modules\Admin\Auxiliary\View\TreeAuxiliary;
+use Modules\Admin\Services\MenusService;
+use Modules\Admin\Services\SettingService;
+use Spatie\Permission\Models\Permission;
+
+class BaseController extends Controller
+{
+    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
+
+    /**
+     * 默认布局模版
+     * @var string
+     */
+    protected $layout = 'admin::layouts.sub';
+
+    /**
+     * 是否开启布局模版
+     * @var boolean
+     */
+    protected $isLayout = true;
+
+    /**
+     * 高亮菜单
+     * @var array
+     */
+    public $menusActive = ['adminDashboard', 'adminDashboardWelcome', ''];
+
+    /**
+     * 视图方法
+     * @var
+     */
+    protected $layoutView;
+
+    public function __construct()
+    {
+//        $this->middleware(['auth:admin', 'roles']);
+        $this->middleware(['auth']);
+        $this->setLayout($this->layout);
+    }
+
+    /**
+     * 视图函数
+     * @param string $view
+     * @param array  $date
+     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
+     */
+    public function view($view = '', $date = [], $layoutMode = true)
+    {
+        // 获取并将用户信息视图共享
+        $user = Auth::guard('web')->user();
+        View::share('user', $user);
+
+//        if (Auth::guard('web')->user()->hasRole('superAdmin')) {
+//            $permissionsList = Permission::all()->pluck('route')->all();
+//        } else {
+//            $permissionsList = Auth::guard('web')->user()->getAllPermissions()->pluck('route')->all();
+//        }
+        //        dump($permissionsList);
+        $permissionsList = [];
+        View::share('permissionsList', $permissionsList);
+        $date['isAjax'] = 0;
+        if (Request::ajax()) {  // 判断Ajax请求
+            $date['isAjax'] = 1;
+            return view($view, $date);
+        }
+
+        // 获取并共享可见菜单信息
+        $menus = new MenusService();
+        $menus = $menus->getMenusList(1);
+        View::share('menus', $menus);
+        // 获取配置信息
+//        $setting = new SettingService();
+//        $setting = $setting->getList();
+//        View::share('setting', $setting->pluck('value', 'name')->all());
+        // 共享菜单高亮信息
+        View::share('menusActive', $this->menusActive);
+        if (!is_null($this->layout) && $this->isLayout && $layoutMode) {
+            return $this->layoutView->nest('content', $view, $date);
+        }
+        return view($view, $date);
+    }
+
+    /**
+     * 地址跳转
+     * @param        $path
+     * @param string $data
+     * @return array|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
+     */
+    protected function redirect($path, $msg = '', $tableId = '')
+    {
+        if (Request::ajax()) {
+            return [
+                'code'    => 0,
+                'message' => 'SUCCESS',
+                'data'    => [
+                    'url'   => $path,
+                    'msg'   => $msg,
+                    'table' => $tableId,
+                ],
+            ];
+        }
+        return redirect($path);
+    }
+
+    /**
+     * 树型视图
+     * @param TreeAuxiliary $treeObj
+     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
+     */
+    public function tree(TreeAuxiliary $treeObj)
+    {
+        $data['path']                = $treeObj->path;
+        $data['items']               = $treeObj->items;
+        $data['columns']             = $treeObj->columns;
+        $data['topActions']          = $treeObj->topActions;
+        $data['actionBtns']          = $treeObj->actionBtns;
+        $data['displayActionOthers'] = $treeObj->displayActionOthers;
+        return $this->view('admin::component.template_tree_list', $data);
+    }
+
+    /**
+     * 表格列表视图
+     * @param TreeAuxiliary $treeObj
+     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
+     */
+    public function tableList(TableAuxiliary $tableObj)
+    {
+        $data['path']           = $tableObj->path;
+        $data['items']          = $tableObj->items;
+        $data['columns']        = $tableObj->columns;
+        $data['searchs']        = $tableObj->searchColumns;
+        $data['primaryKey']     = $tableObj->primaryKey;
+        $data['displayActions'] = $tableObj->displayActions;
+        if (is_string($data['displayActions']['value'])) {
+            $data['displayActions']['value'] = [$data['displayActions']['value']];
+        }
+        $data['actionBtns']          = $tableObj->actionBtns;
+        $data['actionBtnsAttribute'] = $tableObj->actionBtnsAttribute;
+        $data['topActions']          = $tableObj->topActions;
+        $data['displayActionOthers'] = $tableObj->displayActionOthers;
+        $data['topActionOthers']     = $tableObj->topActionOthers;
+        $data                        += Request::except('_token');
+        return $this->view('admin::component.template_table_list', $data);
+    }
+
+    /**
+     * 表格单独视图
+     * @param TreeAuxiliary $treeObj
+     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
+     */
+    public function tableView(TableAuxiliary $tableObj)
+    {
+        $data['items']   = $tableObj->items;
+        $data['columns'] = $tableObj->columns;
+        $data['title']   = $tableObj->title;
+        return $this->view('admin::component.template_table_view', $data);
+    }
+
+    /**
+     * 表单视图
+     * @param FromAuxiliary $fromObj
+     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
+     */
+    public function from(FromAuxiliary $fromObj)
+    {
+        $data['path']       = '/admin/' . $fromObj->path;
+        $data['fromTitle']  = $fromObj->title;
+        $data['columns']    = $fromObj->columns;
+        $data['item']       = $fromObj->item;
+        $data['hasHr']      = $fromObj->hasHr;
+        $data['primaryKey'] = $fromObj->primaryKey;
+        $data['footBtns']   = $fromObj->footBtns;
+        $data['colWidth']   = $fromObj->colWidth;
+        if(strpos($data['path'],'camera') !== false){
+            return $this->view('camera::camera_add', $data);
+        }elseif(strpos($data['path'],'mine') !== false){//path包含mine
+            return $this->view('camera::mine_add', $data);
+        }else{
+            return $this->view('admin::component.template_from', $data);
+        }
+
+//
+    }
+
+    /**
+     * 设置布局模版
+     * @param null $layout
+     */
+    public function setLayout($layout = null)
+    {
+        if (!is_null($layout) && $this->isLayout) {
+            $this->layoutView = view($layout);
+        }
+    }
+
+    protected function error($code = 1, $msg = '', $url = '', $time = 3)
+    {
+        if (Request::ajax()) {
+            return [
+                'code'    => $code,
+                'message' => $msg,
+                'url'     => $url,
+            ];
+        }
+        $data['msg'] = $msg;
+        $data['url'] = $url;
+        if (empty($url)) {
+            $data['url'] = url()->previous();
+        }
+        $data['time'] = $time;
+        return $this->view('admin::layouts.error', $data);
+    }
+
+    protected function success($data = '', $msg = null, $url = '', $time = 3)
+    {
+        if (Request::ajax()) {
+            $result = [
+                'code'    => 0,
+                'message' => $msg ?? 'SUCCESS',
+                'data'    => $data,
+            ];
+            if (!empty($url)) {
+                $result['url'] = $url;
+            }
+            return $result;
+        }
+        $_data['url'] = $url;
+        if (empty($url)) {
+            $_data['url'] = url()->previous();
+        }
+        $_data['data'] = $data;
+        $_data['time'] = $time;
+        return $this->view('admin::layouts.success', $_data);
+    }
+
+}

+ 111 - 0
Modules/Admin/Http/Controllers/LoginController.php

@@ -0,0 +1,111 @@
+<?php
+
+namespace Modules\Admin\Http\Controllers;
+
+use Illuminate\Foundation\Auth\AuthenticatesUsers;
+use Illuminate\Http\Request;
+use Illuminate\Routing\Controller;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Log;
+use Modules\Admin\Services\FilterService;
+use Modules\Admin\Services\SettingService;
+use DB;
+class LoginController extends Controller
+{
+    use AuthenticatesUsers;
+
+    /**
+     * 登陆后的跳转页面
+     *
+     * @var string
+     */
+    protected $redirectTo = '/admin';
+
+    /**
+     * Create a new controller instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        $this->middleware('guest')->except('logout');
+    }
+
+    //登录页面
+    public function loginView(Request $request)
+    {
+        $filter = FilterService::check_ip();
+        if (Auth::guard('web')->check()) {
+            return redirect('/admin');
+        }
+
+        return view('admin::login');
+    }
+
+    //登录动作
+    public function doLogin(Request $request)
+    {
+        $request['password'] = base64_decode($request->input('password'));
+        $this->validateLogin($request);
+
+        // If the class is using the ThrottlesLogins trait, we can automatically throttle
+        // the login attempts for this application. We'll key this by the username and
+        // the IP address of the client making these requests into this application.
+        if (method_exists($this, 'hasTooManyLoginAttempts') &&
+            $this->hasTooManyLoginAttempts($request)) {
+            $this->fireLockoutEvent($request);
+            return $this->sendLockoutResponse($request);
+        }
+
+        $valid = validPass($request['password']);
+        if (is_string($valid)) {
+            $this->guard()->logout();
+            $request->session()->invalidate();
+            return [
+                'code'    => 1,
+                'message' => '密码限制:' . $valid . ',请找管理员修改',
+            ];
+        }
+
+        if ($this->attemptLogin($request)) {
+//            $roles = $this->guard()->user()->getRoleNames()->toArray();
+//            if (count($roles) == 0 || (count($roles) == 1 && $roles[0] == 'PuTongZhiYuan')) {
+//                $this->guard()->logout();
+//                $request->session()->invalidate();
+//                return [
+//                    'code'    => 1,
+//                    'message' => '没有登录权限',
+//                ];
+//            }
+            $token = $request->input('staff_num') . "," . $request->input('password') . "," . $request->getClientIp();
+            $token = base64_encode($token);
+            setcookie("token", $token, time() + 7200, "/", ".nxjiewei.com");
+            return $this->sendLoginResponse($request);
+        }
+
+        // If the login attempt was unsuccessful we will increment the number of attempts
+        // to login and redirect the user back to the login form. Of course, when this
+        // user surpasses their maximum number of attempts they will get locked out.
+        $this->incrementLoginAttempts($request);
+        return $this->sendFailedLoginResponse($request);
+    }
+
+    protected function sendLoginResponse(Request $request)
+    {
+        $request->session()->regenerate();
+        $this->clearLoginAttempts($request);
+        return [
+            'code'    => 0,
+            'message' => '登录成功',
+        ];
+    }
+
+    /**
+     * 用户名验证字段
+     * @return string
+     */
+    public function username()
+    {
+        return 'staff_num';
+    }
+}

+ 179 - 0
Modules/Admin/Http/Controllers/MenusController.php

@@ -0,0 +1,179 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: qiuzijian
+ * Date: 2021-04-15
+ * Time: 11:24
+ */
+
+namespace Modules\Admin\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Storage;
+use Modules\Admin\Auxiliary\View\FromAuxiliary;
+use Modules\Admin\Auxiliary\View\TreeAuxiliary;
+use Modules\Admin\Http\Requests\MenusRequest;
+use Modules\Admin\Services\MenusService;
+use Spatie\Permission\Models\Permission;
+
+class MenusController extends BaseController
+{
+    public function __construct()
+    {
+        parent::__construct();
+        $this->menusActive[0] = 'adminSetting';
+        $this->menusActive[1] = 'adminSettingMenus';
+    }
+
+    /**
+     * 菜单列表
+     * @return mixed
+     */
+    public function index()
+    {
+        $menusService = new MenusService();
+        $menusAll     = $menusService->getMenusList();
+
+        $treeObj = new TreeAuxiliary('menus', $menusAll);
+        $treeObj->column('title', '菜单名')
+                ->column('slug', '标识')
+                ->column('path', '路由')
+                ->column('sort', '排序')
+                ->column('show', '是否可见')->display(
+                function ($show) {
+                    $value = ['否', '是'];
+                    return $value[$show];
+                }
+            );
+        return $this->tree($treeObj);
+    }
+
+    /**
+     * 添加菜单页面
+     * @return mixed
+     */
+    public function add()
+    {
+        $menusService   = new MenusService();
+        $menusAll       = $menusService->getMenusList();
+        $fromObj        = new FromAuxiliary('menus/add');
+        $fromObj->title = '添加菜单';
+        $fromObj->tree_select('parent_id', '父级菜单', $menusAll)
+                ->icon('icon', '图标')
+                ->input('title', '菜单名称')
+//            ->input('slug', '菜单标识')
+                ->input('path', '访问路由')
+                ->input('sort', '排序', 10)
+                ->radio('show', '是否显示', [1 => '是', 0 => '否'], 1);
+
+        return $this->from($fromObj);
+    }
+
+    /**
+     * 菜单添加请求
+     * @param MenusRequest $request
+     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
+     */
+    public function addPost(Request $request)
+    {
+        $menus  = new MenusService();
+        $result = $menus->addMenu($request->all());
+        if ($result == 'has') {
+            return $this->error(1, '菜单标识重复,请修改后重新提交');
+        }
+        return $this->redirect('admin/menus/list');
+    }
+
+    /**
+     * 修改菜单页面
+     * @param Request $request
+     * @return mixed
+     */
+    public function edit(Request $request)
+    {
+        $menuId = $request->input('id');
+        if (!$menuId) {
+            return false;
+        }
+        $menusService = new MenusService();
+        $menusAll     = $menusService->getMenusList();
+        $currentMenu  = $menusService->getMenuInfo($menuId);
+
+        $fromObj        = new FromAuxiliary('menus/edit', $currentMenu);
+        $fromObj->title = '修改菜单';
+        $fromObj->tree_select('parent_id', '父级菜单', $menusAll, $currentMenu['parent_id'])
+                ->icon('icon', '图标')
+                ->input('title', '菜单名称')
+//            ->input('slug', '菜单标识')
+                ->input('path', '访问路由')
+                ->input('sort', '排序')
+                ->radio('show', '是否显示', [1 => '是', 0 => '否']);
+
+        return $this->from($fromObj);
+    }
+
+    /**
+     * 修改菜单请求
+     * @param MenusRequest $request
+     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
+     */
+    public function editPost(MenusRequest $request)
+    {
+        if ($request->input('id') == $request->input('parent_id')) {
+            return $this->error(1, '父级不能选择自己');
+        }
+        $menus = new MenusService();
+        $menus->editMenu($request->all());
+        return $this->redirect('admin/menus/list');
+    }
+
+    public function delPost(Request $request)
+    {
+        $menuId = $request->input('id');
+        if (!$menuId) {
+            return false;
+        }
+        $menus = new MenusService();
+        $menus->delMenu($menuId);
+        return $this->redirect('admin/menus/list');
+    }
+
+    /**
+     * 菜单导出文件
+     * @return string
+     */
+    public function makeMenuToFile()
+    {
+        $menusService = new MenusService();
+        $menusAll     = $menusService->getMenusList();
+        $menus        = $this->menuFilter($menusAll);
+//        $apiMenusAll  = $menusService->getMenusList('', 'api');
+//        $apiMenus     = $this->menuFilter($apiMenusAll);
+
+        Storage::put('menulist.php', var_export($menus, true));
+//        Storage::put('apimenulist.php', var_export($apiMenus, true));
+        return 'ok';
+    }
+
+    protected function menuFilter($menuList)
+    {
+        $menus = [];
+        foreach ($menuList as $menu) {
+            $_menu = [
+                "icon"  => $menu['icon'],
+                "title" => $menu['title'],
+                "slug"  => $menu['slug'],
+                "path"  => $menu['path'],
+                "sort"  => $menu['sort'],
+                "show"  => $menu['show'],
+                "child" => $menu['child'],
+            ];
+            if (count($menu['child']) > 0) {
+                $_menu['child'] = $this->menuFilter($menu['child']);
+            }
+            $menus[] = $_menu;
+        }
+        return $menus;
+    }
+}

+ 225 - 0
Modules/Admin/Http/Controllers/UsersController.php

@@ -0,0 +1,225 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: qiuzijian
+ * Date: 2021-04-15
+ * Time: 17:28
+ */
+
+namespace Modules\Admin\Http\Controllers;
+
+use App\User;
+use Illuminate\Http\Request;
+use Modules\Admin\Auxiliary\View\FromAuxiliary;
+use Modules\Admin\Auxiliary\View\TableAuxiliary;
+use Modules\Admin\Enum\UserEnum;
+use Modules\Admin\Services\UsersService;
+use Spatie\Permission\Models\Permission;
+use DB;
+
+class UsersController extends BaseController
+{
+    public function __construct()
+    {
+        parent::__construct();
+        $this->menusActive[0] = 'adminUsers';
+        $this->menusActive[1] = 'adminUsersList';
+    }
+
+    //用户列表
+    public function userList(Request $request)
+    {
+        $this->menusActive[0] = 'adminUsers';
+        $this->menusActive[1] = 'adminUsersList';
+        $query = User::where('id', '>', 0);
+
+        if ($request->has('name_staffNum_mobile')) {
+            $query = $query->where('staff_num', 'like', '%' . $request->input('name_staffNum_mobile') . '%')
+                           ->orWhere('mobile', 'like', '%' . $request->input('name_staffNum_mobile') . '%')
+                           ->orWhere('name', 'like', '%' . $request->input('name_staffNum_mobile') . '%');
+        }
+
+        $users = $query->paginate(50);
+
+        $tableObj             = new TableAuxiliary('users/list', $users);
+        $tableObj->primaryKey = 'staff_num';
+//        $tableObj->topActions          = ['add', 'export', 'import', 'importTemplate'];
+        $tableObj->topActions          = ['add'];
+        $tableObj->displayActionOthers = [
+            [
+                'name'   => '更改权限',
+                'path'   => 'users/roles/edit',
+                'class'  => 'layui-btn-warm',
+                'isShow' => function ($item) {
+                    return true;
+                },
+
+            ],
+            [
+                'name'   => '重置密码',
+                'path'   => 'users/list/resetpassword',
+                'class'  => 'layui-btn-warm',
+                'isShow' => function ($item) {
+                    return true;
+                },
+                'isJump' => 'confirm',
+            ]
+        ];
+
+        $tableObj->search('input', 'name_staffNum_mobile', '姓名、编号或手机号');
+        $tableObj->column('name', '姓名')
+                 ->column('staff_num', '用户编码')
+                 ->column('mobile', '手机号');
+
+
+        return $this->tableList($tableObj);
+    }
+
+    //查看用户详情
+    public function userDetail(Request $request)
+    {
+        $staff_num = $request->input('staff_num');
+        if (empty($staff_num)) {
+            return redirect('/users/list/view');
+        }
+        $user     = User::where('staff_num', $staff_num)->first();
+        $tableObj = new TableAuxiliary('', $user);
+        $tableObj->column("name", "姓名")
+                 ->column("mobile", "手机号")
+                 ->column("staff_num", "员工编码");
+        $tableObj->title = '用户详情';
+        return $this->tableView($tableObj);
+    }
+
+    //添加用户
+    public function add(Request $request)
+    {
+        $fromObj = new FromAuxiliary('users/list/add');
+        $fromObj->input("name", "姓名")
+                ->input("mobile", "手机号")
+                ->input("staff_num", "用户编码");
+        $fromObj->title = '添加职员';
+        return $this->from($fromObj);
+    }
+
+    //添加用户操作
+    public function addPost(Request $request)
+    {
+        if (!$request->has('staff_num') || $request->input('staff_num') == 'admin' || empty($request->input('staff_num'))) {
+            return $this->error(1, '用户编码错误');
+        }
+        if (!$request->has('name') || empty($request->input('name'))) {
+            return $this->error(1, '姓名不能为空');
+        }
+
+        $result = UsersService::addAdminUser($request->all());
+
+        if (!$result['status']) {
+            return $this->error(1, $result['msg']);
+        }
+
+        return redirect('/admin/users/list');
+    }
+
+    //编辑用户
+    public function edit(Request $request)
+    {
+        $staff_num = $request->input('staff_num');
+        if (empty($staff_num)) {
+            return redirect('/admin/users/list');
+        }
+
+        $user = User::where('staff_num', $staff_num)->first();
+
+        $fromObj = new FromAuxiliary('users/list/edit', $user);
+        $fromObj->input("name", "姓名")
+                ->input("mobile", "手机号")
+                ->input("staff_num", "用户编码");
+        $fromObj->title      = '修改用户信息';
+        $fromObj->primaryKey = 'staff_num';
+        return $this->from($fromObj);
+    }
+
+    //编辑用户操作
+    public function editPost(Request $request)
+    {
+        if (!$request->has('staff_num') || $request->input('staff_num') == 'admin' || empty($request->input('staff_num'))) {
+            return $this->error(1, '用户编码错误');
+        }
+        if (!$request->has('name') || empty($request->input('name'))) {
+            return $this->error(1, '姓名不能为空');
+        }
+
+        $result = UsersService::editAdminUser($request->all());
+
+        if (!$result['status']) {
+            return $this->error(1, $result['msg']);
+        }
+
+        return redirect('/admin/users/list');
+    }
+
+    //删除用户
+    public function delPost(Request $request)
+    {
+        if (!$request->has('staff_num')) {
+            return $this->error(1, '缺少必要参数');
+        }
+        if ($request->input('staff_num') == 'admin') {
+            return $this->error(1, '员工编码错误');
+        }
+        if ($request->input('staff_num') == $request->user()['staff_num']) {
+            return $this->error(1, '不能删除自己');
+        }
+
+        $result = UsersService::delAdminUser($request->all());
+        if (!$result['status']) {
+            return $this->error(1, $result['msg']);
+        }
+        return $this->success();
+    }
+
+    //重置用户密码
+    public function resetPassword(Request $request)
+    {
+        if (!$request->has('staff_num')) {
+            return $this->error(1, '缺少必要参数');
+        }
+
+        $result = UsersService::resetPassword($request->all());
+        if (!$result['status']) {
+            return $this->error(1, $result['msg']);
+        }
+        return $this->success();
+    }
+
+    //权限修改
+    public function roles(Request $request)
+    {
+        $params = $request->all();
+        if ($request->isMethod('post')) {
+            $res['mine_role'] = "";
+            if(isset($params['mine_id'])){
+                foreach($params['mine_id'] as $k=>$v){
+                    $res['mine_role'] = $res['mine_role'] . $v . ';';
+                }
+                $res['mine_role'] = substr($res['mine_role'], 0, strlen($res['mine_role']) - 1);
+            }
+            DB::table('users')->where('staff_num',$params['staff_num'])->update($res);
+            $data['code'] = 0;
+            return $data;
+        }
+
+        $mine_parent = DB::table('mine_list')->where('parent_id',0)->where('deleted_at',null)->get();
+        $data['menusAll'] = $mine_parent;
+        $data['title']    = '更改权限';
+        $user = DB::table('users')->where('staff_num',$params['staff_num'])->first();
+        $checkedId = explode(';',$user->mine_role);
+        foreach($checkedId as $k=>$v){
+            $checkedId[$k] = (int)$v;
+        }
+        $data['checkedId'] = $checkedId;
+        $data['staff_num'] = $params['staff_num'];
+        return $this->view('admin::roles', $data);
+    }
+}

+ 0 - 0
Modules/Admin/Http/Middleware/.gitkeep


+ 0 - 0
Modules/Admin/Http/Requests/.gitkeep


+ 42 - 0
Modules/Admin/Http/Requests/MenusRequest.php

@@ -0,0 +1,42 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: qiuzijian
+ * Date: 2021-04-15
+ * Time: 16:01
+ */
+
+namespace Modules\Admin\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class MenusRequest extends FormRequest
+{
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        return [
+            'parent_id' => 'numeric',  // 父级id
+            'icon'      => 'alpha_dash',  // 图标
+            'title'     => 'required',  // 栏目名称
+            //            'slug'      => 'required|alpha_dash',  // 标识
+            'path'      => 'required|string',  // 路由
+            'sort'      => 'numeric',  // 排序
+            'show'      => 'boolean',  // 是否显示
+        ];
+    }
+
+    /**
+     * Determine if the user is authorized to make this request.
+     *
+     * @return bool
+     */
+    public function authorize()
+    {
+        return true;
+    }
+}

+ 0 - 0
Modules/Admin/Providers/.gitkeep


+ 125 - 0
Modules/Admin/Providers/AdminServiceProvider.php

@@ -0,0 +1,125 @@
+<?php
+
+namespace Modules\Admin\Providers;
+
+use Illuminate\Support\ServiceProvider;
+use Illuminate\Database\Eloquent\Factory;
+
+class AdminServiceProvider extends ServiceProvider
+{
+    /**
+     * @var string $moduleName
+     */
+    protected $moduleName = 'Admin';
+
+    /**
+     * @var string $moduleNameLower
+     */
+    protected $moduleNameLower = 'admin';
+
+    /**
+     * Boot the application events.
+     *
+     * @return void
+     */
+    public function boot()
+    {
+        $this->registerTranslations();
+        $this->registerConfig();
+        $this->registerViews();
+        $this->registerFactories();
+        $this->loadMigrationsFrom(module_path($this->moduleName, 'Database/Migrations'));
+    }
+
+    /**
+     * Register the service provider.
+     *
+     * @return void
+     */
+    public function register()
+    {
+        $this->app->register(RouteServiceProvider::class);
+    }
+
+    /**
+     * Register config.
+     *
+     * @return void
+     */
+    protected function registerConfig()
+    {
+        $this->publishes([
+            module_path($this->moduleName, 'Config/config.php') => config_path($this->moduleNameLower . '.php'),
+        ], 'config');
+        $this->mergeConfigFrom(
+            module_path($this->moduleName, 'Config/config.php'), $this->moduleNameLower
+        );
+    }
+
+    /**
+     * Register views.
+     *
+     * @return void
+     */
+    public function registerViews()
+    {
+        $viewPath = resource_path('views/modules/' . $this->moduleNameLower);
+
+        $sourcePath = module_path($this->moduleName, 'Resources/views');
+
+        $this->publishes([
+            $sourcePath => $viewPath
+        ], ['views', $this->moduleNameLower . '-module-views']);
+
+        $this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower);
+    }
+
+    /**
+     * Register translations.
+     *
+     * @return void
+     */
+    public function registerTranslations()
+    {
+        $langPath = resource_path('lang/modules/' . $this->moduleNameLower);
+
+        if (is_dir($langPath)) {
+            $this->loadTranslationsFrom($langPath, $this->moduleNameLower);
+        } else {
+            $this->loadTranslationsFrom(module_path($this->moduleName, 'Resources/lang'), $this->moduleNameLower);
+        }
+    }
+
+    /**
+     * Register an additional directory of factories.
+     *
+     * @return void
+     */
+    public function registerFactories()
+    {
+        if (! app()->environment('production') && $this->app->runningInConsole()) {
+            app(Factory::class)->load(module_path($this->moduleName, 'Database/factories'));
+        }
+    }
+
+    /**
+     * Get the services provided by the provider.
+     *
+     * @return array
+     */
+    public function provides()
+    {
+        return [];
+    }
+
+    private function getPublishableViewPaths(): array
+    {
+        $paths = [];
+        foreach (\Config::get('view.paths') as $path) {
+            if (is_dir($path . '/modules/' . $this->moduleNameLower)) {
+                $paths[] = $path . '/modules/' . $this->moduleNameLower;
+            }
+        }
+        return $paths;
+    }
+}

+ 69 - 0
Modules/Admin/Providers/RouteServiceProvider.php

@@ -0,0 +1,69 @@
+<?php
+
+namespace Modules\Admin\Providers;
+
+use Illuminate\Support\Facades\Route;
+use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
+
+class RouteServiceProvider extends ServiceProvider
+{
+    /**
+     * The module namespace to assume when generating URLs to actions.
+     *
+     * @var string
+     */
+    protected $moduleNamespace = 'Modules\Admin\Http\Controllers';
+
+    /**
+     * Called before routes are registered.
+     *
+     * Register any model bindings or pattern based filters.
+     *
+     * @return void
+     */
+    public function boot()
+    {
+        parent::boot();
+    }
+
+    /**
+     * Define the routes for the application.
+     *
+     * @return void
+     */
+    public function map()
+    {
+        $this->mapApiRoutes();
+
+        $this->mapWebRoutes();
+    }
+
+    /**
+     * Define the "web" routes for the application.
+     *
+     * These routes all receive session state, CSRF protection, etc.
+     *
+     * @return void
+     */
+    protected function mapWebRoutes()
+    {
+        Route::middleware('web')
+            ->namespace($this->moduleNamespace)
+            ->group(module_path('Admin', '/Routes/web.php'));
+    }
+
+    /**
+     * Define the "api" routes for the application.
+     *
+     * These routes are typically stateless.
+     *
+     * @return void
+     */
+    protected function mapApiRoutes()
+    {
+        Route::prefix('api')
+            ->middleware('api')
+            ->namespace($this->moduleNamespace)
+            ->group(module_path('Admin', '/Routes/api.php'));
+    }
+}

+ 0 - 0
Modules/Admin/Resources/assets/.gitkeep


+ 0 - 0
Modules/Admin/Resources/assets/js/app.js


+ 0 - 0
Modules/Admin/Resources/assets/sass/app.scss


+ 0 - 0
Modules/Admin/Resources/lang/.gitkeep


+ 0 - 0
Modules/Admin/Resources/views/.gitkeep


+ 8 - 0
Modules/Admin/Resources/views/component/breadcrumb.blade.php

@@ -0,0 +1,8 @@
+@if(isset($menus) && count($menus) > 0)
+    @foreach($menus as $menu)
+        @if($menusActive[$num] == $menu['slug'])
+            <a href=""><span uk-icon="icon:{{ $menu['icon'] }}"></span> {{ $menu['title'] }}</a>
+            @include('admin::component.breadcrumb', ['menus' => $menu['child'], 'num' => $num + 1])
+        @endif
+    @endforeach
+@endif

+ 25 - 0
Modules/Admin/Resources/views/component/excel_table.blade.php

@@ -0,0 +1,25 @@
+<table>
+    <thead>
+    @if(count($header) > 0)
+        <tr>
+            @foreach($header as $head)
+                <th rowspan="{{ $head['row'] }}" colspan="{{ $head['col'] }}">{{ $head['title'] }}</th>
+            @endforeach
+        </tr>
+    @endif
+    <tr>
+        @foreach($titles as $title)
+            <th>{{ $title }}</th>
+        @endforeach
+    </tr>
+    </thead>
+    <tbody>
+    @foreach($items as $item)
+        <tr>
+            @foreach($item as $col)
+                <td>{{ $col }}</td>
+            @endforeach
+        </tr>
+    @endforeach
+    </tbody>
+</table>

+ 142 - 0
Modules/Admin/Resources/views/component/icon_list.blade.php

@@ -0,0 +1,142 @@
+<ul class="iconnav">
+    <li><i class="layui-icon layui-icon-rate-half" data-icon="rate-half" data-code="&#xe6c9;"></i></li>
+    <li><i class="layui-icon layui-icon-rate" data-code="&#xe67b;" data-icon="rate"></i></li>
+    <li><i class="layui-icon layui-icon-rate-solid" data-code="&#xe67a;" data-icon="rate-solid"></i></li>
+    <li><i class="layui-icon layui-icon-cellphone" data-code="&#xe678;" data-icon="cellphone"></i></li>
+    <li><i class="layui-icon layui-icon-vercode" data-code="&#xe679;" data-icon="vercode"></i></li>
+    <li><i class="layui-icon layui-icon-login-wechat" data-code="&#xe677;" data-icon="login-wechat"></i></li>
+    <li><i class="layui-icon layui-icon-login-qq" data-code="&#xe676;" data-icon="login-qq"></i></li>
+    <li><i class="layui-icon layui-icon-login-weibo" data-code="&#xe675;" data-icon="login-weibo"></i></li>
+    <li><i class="layui-icon layui-icon-password" data-code="&#xe673;" data-icon="password"></i></li>
+    <li><i class="layui-icon layui-icon-username" data-code="&#xe66f;" data-icon="username"></i></li>
+    <li><i class="layui-icon layui-icon-refresh-3" data-code="&#xe9aa;" data-icon="refresh-3"></i></li>
+    <li><i class="layui-icon layui-icon-auz" data-code="&#xe672;" data-icon="auz"></i></li>
+    <li><i class="layui-icon layui-icon-spread-left" data-code="&#xe66b;" data-icon="spread-left"></i></li>
+    <li><i class="layui-icon layui-icon-shrink-right" data-code="&#xe668;" data-icon="shrink-right"></i></li>
+    <li><i class="layui-icon layui-icon-snowflake" data-code="&#xe6b1;" data-icon="snowflake"></i></li>
+    <li><i class="layui-icon layui-icon-tips" data-code="&#xe702;" data-icon="tips"></i></li>
+    <li><i class="layui-icon layui-icon-note" data-code="&#xe66e;" data-icon="note"></i></li>
+    <li><i class="layui-icon layui-icon-home" data-code="&#xe68e;" data-icon="home"></i></li>
+    <li><i class="layui-icon layui-icon-senior" data-code="&#xe674;" data-icon="senior"></i></li>
+    <li><i class="layui-icon layui-icon-refresh" data-code="&#xe669;" data-icon="refresh"></i></li>
+    <li><i class="layui-icon layui-icon-refresh-1" data-code="&#xe666;" data-icon="refresh-1"></i></li>
+    <li><i class="layui-icon layui-icon-flag" data-code="&#xe66c;" data-icon="flag"></i></li>
+    <li><i class="layui-icon layui-icon-theme" data-code="&#xe66a;" data-icon="theme"></i></li>
+    <li><i class="layui-icon layui-icon-notice" data-code="&#xe667;" data-icon="notice"></i></li>
+    <li><i class="layui-icon layui-icon-website" data-code="&#xe7ae;" data-icon="website"></i></li>
+    <li><i class="layui-icon layui-icon-console" data-code="&#xe665;" data-icon="console"></i></li>
+    <li><i class="layui-icon layui-icon-face-surprised" data-code="&#xe664;" data-icon="face-surprised"></i></li>
+    <li><i class="layui-icon layui-icon-set" data-code="&#xe716;" data-icon="set"></i></li>
+    <li><i class="layui-icon layui-icon-template-1" data-code="&#xe656;" data-icon="template-1"></i></li>
+    <li><i class="layui-icon layui-icon-app" data-code="&#xe653;" data-icon="app"></i></li>
+    <li><i class="layui-icon layui-icon-template" data-code="&#xe663;" data-icon="template"></i></li>
+    <li><i class="layui-icon layui-icon-praise" data-code="&#xe6c6;" data-icon="praise"></i></li>
+    <li><i class="layui-icon layui-icon-tread" data-code="&#xe6c5;" data-icon="tread"></i></li>
+    <li><i class="layui-icon layui-icon-male" data-code="&#xe662;" data-icon="male"></i></li>
+    <li><i class="layui-icon layui-icon-female" data-code="&#xe661;" data-icon="female"></i></li>
+    <li><i class="layui-icon layui-icon-camera" data-code="&#xe660;" data-icon="camera"></i></li>
+    <li><i class="layui-icon layui-icon-camera-fill" data-code="&#xe65d;" data-icon="camera-fill"></i></li>
+    <li><i class="layui-icon layui-icon-more" data-code="&#xe65f;" data-icon="more"></i></li>
+    <li><i class="layui-icon layui-icon-more-vertical" data-code="&#xe671;" data-icon="more-vertical"></i></li>
+    <li><i class="layui-icon layui-icon-rmb" data-code="&#xe65e;" data-icon="rmb"></i></li>
+    <li><i class="layui-icon layui-icon-dollar" data-code="&#xe659;" data-icon="dollar"></i></li>
+    <li><i class="layui-icon layui-icon-diamond" data-code="&#xe735;" data-icon="diamond"></i></li>
+    <li><i class="layui-icon layui-icon-fire" data-code="&#xe756;" data-icon="fire"></i></li>
+    <li><i class="layui-icon layui-icon-return" data-code="&#xe65c;" data-icon="return"></i></li>
+    <li><i class="layui-icon layui-icon-location" data-code="&#xe715;" data-icon="location"></i></li>
+    <li><i class="layui-icon layui-icon-read" data-code="&#xe705;" data-icon="read"></i></li>
+    <li><i class="layui-icon layui-icon-survey" data-code="&#xe6b2;" data-icon="survey"></i></li>
+    <li><i class="layui-icon layui-icon-face-smile" data-code="&#xe6af;" data-icon="face-smile"></i></li>
+    <li><i class="layui-icon layui-icon-face-cry" data-code="&#xe69c;" data-icon="face-cry"></i></li>
+    <li><i class="layui-icon layui-icon-cart-simple" data-code="&#xe698;" data-icon="cart-simple"></i></li>
+    <li><i class="layui-icon layui-icon-cart" data-code="&#xe657;" data-icon="cart"></i></li>
+    <li><i class="layui-icon layui-icon-next" data-code="&#xe65b;" data-icon="next"></i></li>
+    <li><i class="layui-icon layui-icon-prev" data-code="&#xe65a;" data-icon="prev"></i></li>
+    <li><i class="layui-icon layui-icon-upload-drag" data-code="&#xe681;" data-icon="upload-drag"></i></li>
+    <li><i class="layui-icon layui-icon-upload" data-code="&#xe67c;" data-icon="upload"></i></li>
+    <li><i class="layui-icon layui-icon-download-circle" data-code="&#xe601;" data-icon="download-circle"></i></li>
+    <li><i class="layui-icon layui-icon-component" data-code="&#xe857;" data-icon="component"></i></li>
+    <li><i class="layui-icon layui-icon-file-b" data-code="&#xe655;" data-icon="file-b"></i></li>
+    <li><i class="layui-icon layui-icon-user" data-code="&#xe770;" data-icon="user"></i></li>
+    <li><i class="layui-icon layui-icon-find-fill" data-code="&#xe670;" data-icon="find-fill"></i></li>
+    <li><i class="layui-icon layui-icon-add-1" data-code="&#xe654;" data-icon="add-1"></i></li>
+    <li><i class="layui-icon layui-icon-play" data-code="&#xe652;" data-icon="play"></i></li>
+    <li><i class="layui-icon layui-icon-pause" data-code="&#xe651;" data-icon="pause"></i></li>
+    <li><i class="layui-icon layui-icon-headset" data-code="&#xe6fc;" data-icon="headset"></i></li>
+    <li><i class="layui-icon layui-icon-video" data-code="&#xe6ed;" data-icon="video"></i></li>
+    <li><i class="layui-icon layui-icon-voice" data-code="&#xe688;" data-icon="voice"></i></li>
+    <li><i class="layui-icon layui-icon-speaker" data-code="&#xe645;" data-icon="speaker"></i></li>
+    <li><i class="layui-icon layui-icon-fonts-del" data-code="&#xe64f;" data-icon="fonts-del"></i></li>
+    <li><i class="layui-icon layui-icon-fonts-code" data-code="&#xe64e;" data-icon="fonts-code"></i></li>
+    <li><i class="layui-icon layui-icon-fonts-html" data-code="&#xe64b;" data-icon="fonts-html"></i></li>
+    <li><i class="layui-icon layui-icon-fonts-strong" data-code="&#xe62b;" data-icon="fonts-strong"></i></li>
+    <li><i class="layui-icon layui-icon-unlink" data-code="&#xe64d;" data-icon="unlink"></i></li>
+    <li><i class="layui-icon layui-icon-picture" data-code="&#xe64a;" data-icon="picture"></i></li>
+    <li><i class="layui-icon layui-icon-link" data-code="&#xe64c;" data-icon="link"></i></li>
+    <li><i class="layui-icon layui-icon-face-smile-b" data-code="&#xe650;" data-icon="face-smile-b"></i></li>
+    <li><i class="layui-icon layui-icon-align-left" data-code="&#xe649;" data-icon="align-left"></i></li>
+    <li><i class="layui-icon layui-icon-align-right" data-code="&#xe648;" data-icon="align-right"></i></li>
+    <li><i class="layui-icon layui-icon-align-center" data-code="&#xe647;" data-icon="align-center"></i></li>
+    <li><i class="layui-icon layui-icon-fonts-u" data-code="&#xe646;" data-icon="fonts-u"></i></li>
+    <li><i class="layui-icon layui-icon-fonts-i" data-code="&#xe644;" data-icon="fonts-i"></i></li>
+    <li><i class="layui-icon layui-icon-tabs" data-code="&#xe62a;" data-icon="tabs"></i></li>
+    <li><i class="layui-icon layui-icon-radio" data-code="&#xe643;" data-icon="radio"></i></li>
+    <li><i class="layui-icon layui-icon-circle" data-code="&#xe63f;" data-icon="circle"></i></li>
+    <li><i class="layui-icon layui-icon-edit" data-code="&#xe642;" data-icon="edit"></i></li>
+    <li><i class="layui-icon layui-icon-share" data-code="&#xe641;" data-icon="share"></i></li>
+    <li><i class="layui-icon layui-icon-delete" data-code="&#xe640;" data-icon="delete"></i></li>
+    <li><i class="layui-icon layui-icon-form" data-code="&#xe63c;" data-icon="form"></i></li>
+    <li><i class="layui-icon layui-icon-cellphone-fine" data-code="&#xe63b;" data-icon="cellphone-fine"></i></li>
+    <li><i class="layui-icon layui-icon-dialogue" data-code="&#xe63a;" data-icon="dialogue"></i></li>
+    <li><i class="layui-icon layui-icon-fonts-clear" data-code="&#xe639;" data-icon="fonts-clear"></i></li>
+    <li><i class="layui-icon layui-icon-layer" data-code="&#xe638;" data-icon="layer"></i></li>
+    <li><i class="layui-icon layui-icon-date" data-code="&#xe637;" data-icon="date"></i></li>
+    <li><i class="layui-icon layui-icon-water" data-code="&#xe636;" data-icon="water"></i></li>
+    <li><i class="layui-icon layui-icon-code-circle" data-code="&#xe635;" data-icon="code-circle"></i></li>
+    <li><i class="layui-icon layui-icon-carousel" data-code="&#xe634;" data-icon="carousel"></i></li>
+    <li><i class="layui-icon layui-icon-prev-circle" data-code="&#xe633;" data-icon="prev-circle"></i></li>
+    <li><i class="layui-icon layui-icon-layouts" data-code="&#xe632;" data-icon="layouts"></i></li>
+    <li><i class="layui-icon layui-icon-util" data-code="&#xe631;" data-icon="util"></i></li>
+    <li><i class="layui-icon layui-icon-templeate-1" data-code="&#xe630;" data-icon="templeate-1"></i></li>
+    <li><i class="layui-icon layui-icon-upload-circle" data-code="&#xe62f;" data-icon="upload-circle"></i></li>
+    <li><i class="layui-icon layui-icon-tree" data-code="&#xe62e;" data-icon="tree"></i></li>
+    <li><i class="layui-icon layui-icon-table" data-code="&#xe62d;" data-icon="table"></i></li>
+    <li><i class="layui-icon layui-icon-chart" data-code="&#xe62c;" data-icon="chart"></i></li>
+    <li><i class="layui-icon layui-icon-chart-screen" data-code="&#xe629;" data-icon="chart-screen"></i></li>
+    <li><i class="layui-icon layui-icon-engine" data-code="&#xe628;" data-icon="engine"></i></li>
+    <li><i class="layui-icon layui-icon-triangle-d" data-code="&#xe625;" data-icon="triangle-d"></i></li>
+    <li><i class="layui-icon layui-icon-triangle-r" data-code="&#xe623;" data-icon="triangle-r"></i></li>
+    <li><i class="layui-icon layui-icon-file" data-code="&#xe621;" data-icon="file"></i></li>
+    <li><i class="layui-icon layui-icon-set-sm" data-code="&#xe620;" data-icon="set-sm"></i></li>
+    <li><i class="layui-icon layui-icon-add-circle" data-code="&#xe61f;" data-icon="add-circle"></i></li>
+    <li><i class="layui-icon layui-icon-404" data-code="&#xe61c;" data-icon="404"></i></li>
+    <li><i class="layui-icon layui-icon-about" data-code="&#xe60b;" data-icon="about"></i></li>
+    <li><i class="layui-icon layui-icon-up" data-code="&#xe619;" data-icon="up"></i></li>
+    <li><i class="layui-icon layui-icon-down" data-code="&#xe61a;" data-icon="down"></i></li>
+    <li><i class="layui-icon layui-icon-left" data-code="&#xe603;" data-icon="left"></i></li>
+    <li><i class="layui-icon layui-icon-right" data-code="&#xe602;" data-icon="right"></i></li>
+    <li><i class="layui-icon layui-icon-circle-dot" data-code="&#xe617;" data-icon="circle-dot"></i></li>
+    <li><i class="layui-icon layui-icon-search" data-code="&#xe615;" data-icon="search"></i></li>
+    <li><i class="layui-icon layui-icon-set-fill" data-code="&#xe614;" data-icon="set-fill"></i></li>
+    <li><i class="layui-icon layui-icon-group" data-code="&#xe613;" data-icon="group"></i></li>
+    <li><i class="layui-icon layui-icon-friends" data-code="&#xe612;" data-icon="friends"></i></li>
+    <li><i class="layui-icon layui-icon-reply-fill" data-code="&#xe611;" data-icon="reply-fill"></i></li>
+    <li><i class="layui-icon layui-icon-menu-fill" data-code="&#xe60f;" data-icon="menu-fill"></i></li>
+    <li><i class="layui-icon layui-icon-log" data-code="&#xe60e;" data-icon="log"></i></li>
+    <li><i class="layui-icon layui-icon-picture-fine" data-code="&#xe60d;" data-icon="picture-fine"></i></li>
+    <li><i class="layui-icon layui-icon-face-smile-fine" data-code="&#xe60c;" data-icon="face-smile-fine"></i></li>
+    <li><i class="layui-icon layui-icon-list" data-code="&#xe60a;" data-icon="list"></i></li>
+    <li><i class="layui-icon layui-icon-release" data-code="&#xe609;" data-icon="release"></i></li>
+    <li><i class="layui-icon layui-icon-ok" data-code="&#xe605;" data-icon="ok"></i></li>
+    <li><i class="layui-icon layui-icon-help" data-code="&#xe607;" data-icon="help"></i></li>
+    <li><i class="layui-icon layui-icon-chat" data-code="&#xe606;" data-icon="chat"></i></li>
+    <li><i class="layui-icon layui-icon-top" data-code="&#xe604;" data-icon="top"></i></li>
+    <li><i class="layui-icon layui-icon-star" data-code="&#xe600;" data-icon="star"></i></li>
+    <li><i class="layui-icon layui-icon-star-fill" data-code="&#xe658;" data-icon="star-fill"></i></li>
+    <li><i class="layui-icon layui-icon-close-fill" data-code="&#x1007;" data-icon="close-fill"></i></li>
+    <li><i class="layui-icon layui-icon-close" data-code="&#x1006;" data-icon="close"></i></li>
+    <li><i class="layui-icon layui-icon-ok-circle" data-code="&#x1005;" data-icon="ok-circle"></i></li>
+    <li><i class="layui-icon layui-icon-add-circle-fine" data-code="&#xe608;" data-icon="add-circle-fine"></i></li>
+</ul>
+
+

+ 12 - 0
Modules/Admin/Resources/views/component/multi_select_option.blade.php

@@ -0,0 +1,12 @@
+@foreach($selects as $select)
+    <option value="{{ $select['id'] }}"
+            @if((isset($selectPid) && $selectPid == $select['id']) || (old('parent_id') == $select['id'])) selected @endif>
+        @for($i = 1; $i < $select['tier']; $i++)
+            &nbsp;&nbsp;&nbsp;&nbsp;
+        @endfor
+        {{ $select['title'] }}
+    </option>
+    @if(isset($select['child']) && count($select['child']) > 0)
+        @include('admin::component.multi_select_option', ['selects' => $select['child']])
+    @endif
+@endforeach

+ 17 - 0
Modules/Admin/Resources/views/component/side_menu.blade.php

@@ -0,0 +1,17 @@
+@foreach($menus as $menu)
+    <li data-level="{{ $tier }}" id="menu_{{ $menu['slug'] }}"><a
+            @if(count($menu['child']) == 0) _href="{{ $menu['path'] }}"
+            @else href="javascript:void(0);" @endif style="padding-left:{{ $tier*20 }}px">
+            <i class="layui-icon layui-icon-{{ $menu['icon'] }}"></i>
+            <cite>{{ $menu['title'] }}</cite>
+            @if(count($menu['child']) > 0)
+                <i class="iconfont nav_right">&#xe697;</i>
+            @endif
+        </a>
+        @if(count($menu['child']) > 0)
+            <ul class="sub-menu">
+                @include('admin::component.side_menu', ['menus' => $menu['child'], 'tier' => $tier + 1])
+            </ul>
+        @endif
+    </li>
+@endforeach

+ 960 - 0
Modules/Admin/Resources/views/component/template_from.blade.php

@@ -0,0 +1,960 @@
+<style>
+    .layui-upload-list {
+        width: auto;
+        height: auto;
+        margin-bottom: 0;
+    }
+
+    .layui-elem-quote {
+        padding-bottom: 5px;
+    }
+
+    .layui-upload-img {
+        /*width: 92px;*/
+        height: 92px;
+    }
+
+    hr {
+        margin: 15px 0;
+    }
+
+    .uk-alert-danger {
+        background: #fff1f0;
+        color: #d85030;
+        margin-bottom: 15px;
+        padding: 10px;
+        border: 1px solid rgba(216, 80, 48, .3);
+        border-radius: 4px;
+        text-shadow: 0 1px 0 #fff;
+    }
+
+    .imgItem {
+        display: inline-block;
+        position: relative;
+        margin: 0 10px 10px 0;
+    }
+
+    .imgItem .layui-close {
+        position: absolute;
+        top: 0;
+        right: 0;
+        height: 16px;
+        line-height: 16px;
+        text-align: center;
+        color: #000;
+        width: 16px;
+        border: 1px solid #000;
+        background-color: #fff;
+    }
+
+    iframe.fr-iframe {
+        padding: 0 20px;
+    }
+
+    .fr-wrapper.show-placeholder .fr-placeholder {
+        padding-left: 30px !important;
+    }
+
+    .layui-form-label {
+        width: {{ $colWidth }}px;
+    }
+
+    .layui-input-block {
+        margin-left: {{ $colWidth + 30 }}px;
+    }
+
+    .weadmin-body {
+        overflow: initial;
+    }
+</style>
+<script src="/js/admin/xm-select.js"></script>
+<script src="/laydate/laydate.js"></script>
+<form class="layui-form" id="form-unify" method="post" action="{{ $path ?? '' }}" style="padding:20px;">
+    @csrf
+    <h2 class="uk-modal-title">{{ $fromTitle }}</h2>
+    @if(isset($item[$primaryKey]))
+        <input type="hidden" name="{{ $primaryKey }}" value="{{ $item[$primaryKey] }}">
+    @endif
+    <hr>
+
+    @if ($errors->any())
+        <div class="uk-alert-danger" uk-alert>
+            <p>{{ $errors->first() }}</p>
+        </div>
+    @endif
+
+    @foreach($columns as $key => $column)
+        @switch($column['type'])
+            @case('text')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block" style="line-height: 36px;">
+                    @if(isset($column['default']) && !empty($column['default']))
+                        @if($column['default'] instanceof Closure)
+                            {!! $column['default']($item) !!}
+                        @else
+                            {!! $column['default'] !!}
+                        @endif
+                    @else
+                        {!!  $item[$key] ?? '' !!}
+                    @endif
+                </div>
+            </div>
+            @break
+
+            @case('input')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <input class="layui-input" type="text"
+                           placeholder="{{ $column['placeholder'] ?? '请输入'.$column['label'] }}"
+                           name="{{ $key }}"
+                           value="{{ $item[$key] ?? (old($key) ?? ($column['default'] ?? '')) }}"/>
+                </div>
+            </div>
+            @break
+
+            @case('password')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <input class="layui-input" type="password"
+                           placeholder="{{ $column['placeholder'] ?? '请输入'.$column['label'] }}"
+                           name="{{ $key }}"
+                           value="{{ $item[$key] ?? (old($key) ?? ($column['default'] ?? '')) }}"/>
+                </div>
+            </div>
+            @break
+
+            @case('radio')
+            <div class="layui-form-item">
+                <div class="layui-form-label">{{ $column['label'] }}</div>
+                <div class="layui-input-block">
+                    @foreach($column['options'] as $k => $col)
+                        <label><input type="radio" name="{{ $key }}" value="{{ $k }}"
+                                      @if((isset($item[$key]) && $item[$key] == $k) ||
+                                      old($key) === $k ||
+                                      (isset($column['default']) && $column['default'] === $k)) checked
+                                      @endif title="{{ $col }}"/>
+                        </label>
+                    @endforeach
+                </div>
+            </div>
+            @break
+
+            @case('checkbox')
+            <div class="layui-form-item">
+                <div class="layui-form-label">{{ $column['label'] }}</div>
+                <div class="layui-input-block">
+                    @foreach($column['options'] as $k => $col)
+                        <input type="checkbox" name="{{ $key.'['.$k.']' }}" value="{{ $k }}"
+                               @if((isset($item[$key]) && in_array($k, $item[$key])) ||
+                               (old($key) !== null && in_array($k, old($key))) ||
+                               (isset($column['default']) && !empty($column['default']) && in_array($k, $column['default']))) checked
+                               @endif title="{{ $col }}" lay-filter="demo{{ $k }}"/>
+                    @endforeach
+                </div>
+            </div>
+            @break
+
+            @case('textarea')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                <textarea class="layui-textarea" name="{{ $key }}" cols="30" rows="3"
+                          placeholder="{{ $column['placeholder'] ?? '请输入'.$column['label'] }}">{{ $item[$key] ?? (old($key) ?? ($column['default'] ?? '')) }}</textarea>
+                </div>
+            </div>
+            @break
+
+            @case('select')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <select name="{{ $key }}">
+                        <option value="0" @if(!isset($item)) selected @endif>无</option>
+                        @if(count($column['options']) > 0)
+                            @foreach($column['options'] as $k => $col)
+                                <option value="{{ $k }}"
+                                        @if($column['default'] == $k || (isset($item[$key]) && $item[$key] == $k)) selected @endif>
+                                    {{ $col }}
+                                </option>
+                            @endforeach
+                        @endif
+                    </select>
+                </div>
+            </div>
+            @break
+
+            {{--联动选择--}}
+            @case('xselect')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <select name="{{ $key }}" xm-select="{{ $key }}" xm-select-radio="">
+                        <option value="">无</option>
+                    </select>
+                </div>
+            </div>
+            <script>
+                layui.use(['form', 'layer', 'formSelects'], function () {
+                    var form = layui.form, layer = layui.layer, formSelects = layui.formSelects;
+                    formSelects.config('{{ $key }}', {
+                        keyName: 'title',            //自定义返回数据中name的key, 默认 name
+                        keyVal: 'id',            //自定义返回数据中value的key, 默认 value
+                        keyChildren: 'child',
+                    }, true);
+                    formSelects.data('{{ $key }}', 'local', {
+                        arr: {!! json_encode($column['options'], JSON_UNESCAPED_UNICODE) !!},
+                        linkage: true,
+                        linkageWidth: 160
+                    });
+
+                    //如果有需要默认值的小伙伴请使用formSelects.value
+                    @if(isset($item[$key]))
+                    formSelects.value('{{ $key }}', ['{{ $item[$key] }}']);
+                    @endif
+                });
+            </script>
+            @break
+
+            {{--单选--}}
+            @case('sselect')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <select name="{{ $key }}" xm-select="{{ $key }}" xm-select-radio="" xm-select-search=""
+                            xm-select-search-type="dl">
+                        <option value="">无</option>
+                    </select>
+                </div>
+            </div>
+            <script>
+                layui.use(['form', 'layer', 'formSelects'], function () {
+                    var form = layui.form, layer = layui.layer, formSelects = layui.formSelects;
+                    formSelects.config('{{ $key }}', {
+                        keyName: 'title',            //自定义返回数据中name的key, 默认 name
+                        keyVal: 'id',            //自定义返回数据中value的key, 默认 value
+                        keyChildren: 'child',
+                    }, true);
+                    formSelects.data('{{ $key }}', 'local', {
+                        arr: {!! json_encode($column['options'], JSON_UNESCAPED_UNICODE) !!}
+                    });
+
+                    //如果有需要默认值的小伙伴请使用formSelects.value
+                    @if(isset($item[$key]))
+                    formSelects.value('{{ $key }}', ['{{ $item[$key] }}']);
+                    @endif
+                });
+            </script>
+            @break
+
+            {{--多选--}}
+            @case('mselect')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <select name="{{ $key }}" xm-select="{{ $key }}" xm-select-search=""
+                            xm-select-search-type="dl">
+                        <option value="">无</option>
+                    </select>
+                </div>
+            </div>
+            <script>
+                layui.use(['form', 'layer', 'formSelects'], function () {
+                    var form = layui.form, layer = layui.layer, formSelects = layui.formSelects;
+                    formSelects.config('{{ $key }}', {
+                        keyName: 'title',            //自定义返回数据中name的key, 默认 name
+                        keyVal: 'id',            //自定义返回数据中value的key, 默认 value
+                        keyChildren: 'child',
+                    }, true);
+                    formSelects.data('{{ $key }}', 'local', {
+                        arr: {!! json_encode($column['options'], JSON_UNESCAPED_UNICODE) !!}
+                    });
+
+                    //如果有需要默认值的小伙伴请使用formSelects.value
+                    @if(isset($item[$key]))
+                    formSelects.value('{{ $key }}', {!! json_encode($column['default'],JSON_UNESCAPED_UNICODE) !!});
+                    @endif
+                });
+            </script>
+            @break
+
+            @case('tselect')
+            <div class="layui-form-item" id="section_{{ $key }}">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <div id="{{ $key }}"></div>
+                </div>
+            </div>
+            <script>
+                xmSelect.render({
+                    el: '#{{ $key }}',
+                    name: '{{ $key }}',
+                    @if(isset($column['default']) && !empty($column['default']) && is_array($column['default']) && count($column['default']) > 0)
+                    initValue: {!! json_encode($column['default']) !!},
+                    @endif
+                    autoRow: true,
+                    filterable: true,
+                    tree: {
+                        show: true,
+                        showFolderIcon: true,
+                        showLine: true,
+                        indent: 20,
+                    },
+                    data() {
+                        return {!! json_encode($column['options']) !!};
+                    }
+                });
+            </script>
+            @break
+
+            @case('trselect')
+            <div class="layui-form-item" id="section_{{ $key }}">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <div id="{{ $key }}"></div>
+                </div>
+            </div>
+            <script>
+                xmSelect.render({
+                    el: '#{{ $key }}',
+                    name: '{{ $key }}',
+                    //单选
+                    radio: true,
+                    //选中关闭
+                    clickClose: true,
+                    @if(isset($column['default']) && !empty($column['default']) && is_array($column['default']) && count($column['default']) > 0)
+                    initValue: {!! json_encode($column['default']) !!},
+                    @endif
+                    autoRow: true,
+                    filterable: true,
+                    tree: {
+                        show: true,
+                        showFolderIcon: true,
+                        showLine: true,
+                        indent: 20,
+                    },
+                    data() {
+                        return {!! json_encode($column['options']) !!};
+                    }
+                });
+            </script>
+            @break
+
+            @case('trmselect')
+            <div class="layui-form-item" id="section_{{ $key }}">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <div id="{{ $key }}"></div>
+                </div>
+            </div>
+            <script>
+                xmSelect.render({
+                    el: '#{{ $key }}',
+                    name: '{{ $key }}',
+                    @if(isset($column['default']) && !empty($column['default']) && is_array($column['default']) && count($column['default']) > 0)
+                    initValue: {!! json_encode($column['default']) !!},
+                    @endif
+                    autoRow: true,
+                    filterable: true,
+                    tree: {
+                        show: true,
+                        showFolderIcon: true,
+                        showLine: true,
+                        indent: 20,
+                    },
+                    data() {
+                        return {!! json_encode($column['options']) !!};
+                    }
+                });
+            </script>
+            @break
+
+            @case('date')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <input class="layui-input date-input" type="text"
+                           placeholder="{{ $column['placeholder'] ?? '请输入'.$column['label'] }}"
+                           name="{{ $key }}" autocomplete="off" readonly
+                           disableautocomplete value="{{ $item[$key] ?? (old($key) ?? ($column['default'] ?? '')) }}">
+                </div>
+            </div>
+            @break
+
+            @case('dateMonth')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <input class="layui-input dateMonth-input" type="text"
+                           placeholder="{{ $column['placeholder'] ?? '请输入'.$column['label'] }}"
+                           name="{{ $key }}" autocomplete="off" readonly
+                           disableautocomplete value="{{ $item[$key] ?? (old($key) ?? ($column['default'] ?? '')) }}">
+                </div>
+            </div>
+            @break
+
+            @case('dateYear')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <input class="layui-input dateYear-input" type="text"
+                           placeholder="{{ $column['placeholder'] ?? '请输入'.$column['label'] }}"
+                           name="{{ $key }}" autocomplete="off" readonly
+                           disableautocomplete value="{{ $item[$key] ?? (old($key) ?? ($column['default'] ?? '')) }}">
+                </div>
+            </div>
+            @break
+
+            @case('dateTime')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <input class="layui-input" type="text"
+                           id="{{ $key }}"
+                           placeholder="{{ $column['placeholder'] ?? '请输入'.$column['label'] }}"
+                           lay-key="{{ rand(10000,99999) }}"
+                           name="{{ $key }}" autocomplete="off" readonly
+                           disableautocomplete value="{{ $item[$key] ?? (old($key) ?? ($column['default'] ?? '')) }}">
+                </div>
+            </div>
+            <script>
+                layui.use('laydate', function () {
+                    var laydate = layui.laydate;
+                    //执行一个laydate实例
+                    laydate.render({
+                        elem: '#{{ $key }}'
+                        , type: 'datetime'
+                    });
+                });
+            </script>
+            @break
+
+            @case('time')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <input class="layui-input time-input" type="text"
+                           placeholder="{{ $column['placeholder'] ?? '请输入'.$column['label'] }}"
+                           name="{{ $key }}"
+                           value="{{ $item[$key] ?? (old($key) ?? ($column['default'] ?? '')) }}">
+                </div>
+            </div>
+            @break
+
+            @case('tree_select')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    {{-- {!! json_encode($column) !!} --}}
+                    <select name="{{ $key }}">
+                        @if($column['isShowNull'] == true)
+                            <option value="0" @if(!isset($item)) selected @endif>无</option>
+                        @endif
+                        @if(count($column['options']) > 0)
+                            @include('admin::component.multi_select_option', ['selects' => $column['options'], 'selectPid' => $item[$key] ?? ($column['default'] ?? '')])
+                        @endif
+                    </select>
+                </div>
+            </div>
+            @break
+
+            @case('icon')
+            <div class="layui-form-item" style="position:relative;">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <div id="iconShow" class="layui-form-mid">
+                        <i class="layui-icon layui-icon-{{ ($item[$key] ?? old($key)) ?? 'app' }}"></i>
+                    </div>
+                    <div class="layui-input-inline" id="iconInput">
+                        <input class="layui-input" type="text" placeholder="选择图标" id="iconInput"
+                               name="{{ $key }}" autocomplete="off"
+                               disableautocomplete value="{{ $item[$key] ?? old($key) }}">
+                    </div>
+                </div>
+                <div id="iconBox">
+                    @include('admin::component/icon_list')
+                </div>
+            </div>
+            <script>
+                $(function () {
+                    $('#iconInput').on('click', function () {
+                        $('#iconBox').toggle();
+                    })
+                    $('#iconBox li i').on('click', function () {
+                        var self = $(this);
+                        $('#iconInput input').val(self.data('icon'));
+                        $('#iconShow').html('<i class="layui-icon layui-icon-' + self.data('icon') + '"></i>');
+                        $('#iconBox').hide();
+                    })
+                })
+            </script>
+            @break
+
+            @case('uploadImg')
+            <label class="layui-form-label">{{ $column['label'] }}</label>
+            <div class="layui-upload">
+                <img id="pre" class="layui-upload-img none">
+
+                @if (strlen($column['default']) > 0)
+                    <script>
+                        $('#pre').attr('src', '{{ $column['default'] }}');
+                    </script>
+                @endif
+
+                <span style="display: inline-table;">
+                    <button type="button" class="layui-btn" id="selectImgBtn">上传图片</button>
+                    <p id="uploadTips">
+                        <input type="hidden" name="{{ $key }}" value="{{ $column['default'] ?? '' }}"/>
+                    </p>
+                </span>
+            </div>
+            <style>
+                .layui-upload-img {
+                    /*width: 92px;*/
+                    height: 92px;
+                    margin: 10px 10px 10px 10px;
+                }
+
+                #uploadTips {
+                    line-height: 30px;
+                }
+            </style>
+            <script>
+                layui.use('upload', function () {
+
+                    var $ = layui.jquery
+                        , upload = layui.upload;
+
+                    var uploadInst = upload.render({
+                        elem: '#selectImgBtn'
+                        , url: "{{ $column['uploadURLPath'] }}"
+                        , acceptMime: 'image/jpg, image/png, image/jpeg'
+                        , number: 1
+                        , before: function (obj) {
+                            //预读本地文件示例,不支持ie8
+                            obj.preview(function (index, file, result) {
+                                $('#pre').attr('src', result); //图片链接(base64)
+                            });
+                        }
+                        , done: function (res) {
+                            //如果上传失败
+                            if (res.code > 0) {
+                                return layer.msg('上传失败');
+                            }
+                            //上传成功
+                            $("input[name='{{ $key }}']").val(res.data.image_path);
+                        }
+                        , error: function () {
+                            //演示失败状态,并实现重传
+                            var uploadTips = $('#uploadTips');
+                            uploadTips.html('<span style="color: #FF5722; text-align:center">上传失败</span> <a class="layui-btn layui-btn-xs demo-reload">重试</a>');
+                            uploadTips.find('.demo-reload').on('click', function () {
+                                uploadInst.upload();
+                            });
+                        }
+                    });
+
+                });
+            </script>
+
+            @break
+
+            @case('uploadImgs')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <div class="layui-upload">
+                        <blockquote class="layui-elem-quote layui-quote-nm">
+                            预览图:
+                            <div class="layui-upload-list" id="{{ $key }}_list">
+                                @if(isset($column['default']) && !empty($column['default']))
+                                    @foreach($column['default'] as $imgKey => $image)
+                                        <span id="img{{ $imgKey }}" class="imgItem">
+                                            <img src="{{ $image['path'] }}" alt="{{ $image['imageName'] }}"
+                                                 class="layui-upload-img"/>
+                                            <a href="javascript:void(0);" class="layui-close">X</a>
+                                            <input type="hidden" name="{{ $key }}[{{ $imgKey }}][path]"
+                                                   value="{{ $image['path'] }}">
+                                            <input type="hidden" name="{{ $key }}[{{ $imgKey }}][imageName]"
+                                                   value="{{ $image['imageName'] }}">
+                                        </span>
+                                    @endforeach
+                                @endif
+                            </div>
+                        </blockquote>
+                        <button type="button" class="layui-btn" id="{{ $key }}_btn">多图片上传</button>
+                    </div>
+                </div>
+            </div>
+
+            <script>
+                layui.use('upload', function () {
+                    var upload = layui.upload;
+                    //多图片上传
+                    upload.render({
+                        elem: '#{{ $key }}_btn'
+                        , url: '{{ $column['uploadURLPath'] }}'
+                        , multiple: true
+                        , accept: 'images'
+                        , field: 'image'
+                        , before: function (obj) {
+                            //预读本地文件示例,不支持ie8
+                            obj.preview(function (index, file, result) {
+                                $('#{{ $key }}_list').append('<span id="img' + index + '" class="imgItem"><img src="' + result + '" alt="' + file.name + '" class="layui-upload-img"><a href="javascript:void(0);" class="layui-close">X</a></span>')
+                            });
+                        }
+                        , done: function (res, index) {
+                            if (res.code === 0) {
+                                $('#img' + index).append('<input type="hidden" name="{{ $key }}[' + index + '][path]" value="' + res.data.image_path + '"/>')
+                                $('#img' + index).append('<input type="hidden" name="{{ $key }}[' + index + '][imageName]" value="' + res.data.image_name + '"/>')
+                            }
+                            //上传完毕
+                        }
+                    });
+                });
+            </script>
+            @break
+
+            @case('uploadFiles')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <div class="layui-upload">
+                        <div class="layui-upload-list">
+                            <table class="layui-table">
+                                <thead>
+                                <tr>
+                                    <th>文件名</th>
+                                    <th>状态</th>
+                                    <th>操作</th>
+                                </tr>
+                                </thead>
+                                <tbody id="{{ $key }}_list">
+                                @if(isset($column['default']) && !empty($column['default']))
+                                    @foreach($column['default'] as $fileKey => $file)
+                                        <tr>
+                                            <td>
+                                                <a href="/admin/file/download?name={{ $file['fileName'] }}&path={{ $file['path'] }}"
+                                                   target="_blank"></a>{{ $file['fileName'] }}</td>
+                                            <td></td>
+                                            <td>
+                                                <button class="layui-btn layui-btn-xs layui-btn-danger file-delete">删除
+                                                </button>
+                                                <input type="hidden" name="{{ $key }}[{{ $fileKey }}][path]"
+                                                       value="{{ $file['path'] }}"/>
+                                                <input type="hidden" name="{{ $key }}[{{ $fileKey }}][fileName]"
+                                                       value="{{ $file['fileName'] }}"/>
+                                                <input type="hidden" name="{{ $key }}[{{ $fileKey }}][fileSize]"
+                                                       value="{{ $file['fileSize'] ?? 0 }}"/>
+                                            </td>
+                                        </tr>
+                                    @endforeach
+                                @endif
+                                </tbody>
+                            </table>
+                        </div>
+                        <button type="button" class="layui-btn" id="{{ $key }}_btn">选择上传文件</button>
+                    </div>
+                </div>
+            </div>
+            <script>
+                layui.use('upload', function () {
+                    var upload = layui.upload;
+                    //多文件列表示例
+                    var fileListView = $('#{{ $key }}_list')
+                        , uploadListIns = upload.render({
+                        elem: '#{{ $key }}_btn'
+                        , url: '{{ $column['uploadURLPath'] }}'
+                        , accept: 'file'
+                        , multiple: true
+                        // , auto: false
+                        // , bindAction: '#testListAction'
+                        , choose: function (obj) {
+                            // var files = this.files = obj.pushFile(); //将每次选择的文件追加到文件队列
+                            //读取本地文件
+                            obj.preview(function (index, file, result) {
+                                var tr = $(['<tr id="upload-{{ $key }}-' + index + '">'
+                                    , '<td>' + file.name + '</td>'
+                                    // , '<td>' + (file.size / 1014).toFixed(1) + 'kb</td>'
+                                    , '<td>正在上传,请等待……</td>'
+                                    , '<td>'
+                                    , '<button class="layui-btn layui-btn-xs file-reload layui-hide">重传</button>'
+                                    , '<button class="layui-btn layui-btn-xs layui-btn-danger file-delete">删除</button>'
+                                    , '</td>'
+                                    , '</tr>'].join(''));
+
+                                //单个重传
+                                tr.find('.file-reload').on('click', function () {
+                                    obj.upload(index, file);
+                                });
+
+                                //删除
+                                tr.find('.file-delete').on('click', function () {
+                                    // delete files[index]; //删除对应的文件
+                                    tr.remove();
+                                    uploadListIns.config.elem.next()[0].value = ''; //清空 input file 值,以免删除后出现同名文件不可选
+                                });
+
+                                fileListView.append(tr);
+                            });
+                        }
+                        , done: function (res, index, upload) {
+                            if (res.code === 0) { //上传成功
+                                var tr = fileListView.find('tr#upload-{{ $key }}-' + index)
+                                    , tds = tr.children();
+                                tds.eq(0).html('<a href="/admin/file/download?name=' + res.data.file_name + '&path=' + res.data.file_path + '" target="_blank">' + res.data.file_name + '</a>');
+                                tds.eq(1).html('<span style="color: #5FB878;">上传成功</span>');
+                                // tds.eq(3).html(''); //清空操作
+                                tds.eq(2).append('<input type="hidden" name="{{ $key }}[' + index + '][path]" value="' + res.data.file_path + '"/>');
+                                tds.eq(2).append('<input type="hidden" name="{{ $key }}[' + index + '][fileName]" value="' + res.data.file_name + '"/>');
+                                tds.eq(2).append('<input type="hidden" name="{{ $key }}[' + index + '][fileSize]" value="' + (res.data.file_size == undefined ? 0 : res.data.file_size) + '"/>');
+                                return;
+                                // return delete this.files[index]; //删除文件队列已经上传成功的文件
+                            }
+                            this.error(index, upload);
+                        }
+                        , error: function (index, upload) {
+                            var tr = fileListView.find('tr#upload-{{ $key }}-' + index)
+                                , tds = tr.children();
+                            tds.eq(2).html('<span style="color: #FF5722;">上传失败</span>');
+                            tds.eq(3).find('.file-reload').removeClass('layui-hide'); //显示重传
+                        }
+                    });
+                });
+            </script>
+            @break
+
+            @case('hidden')
+            <input type="hidden" name="{{ $key }}" value="{{ $column['label'] }}"/>
+            @break
+
+            @case('includeBlock')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    @includeIf($column['path'], $column['itemValue'])
+                </div>
+            </div>
+            @break
+
+            @case('editor')
+            <div class="layui-form-item">
+                <label class="layui-form-label">{{ $column['label'] }}</label>
+                <div class="layui-input-block">
+                    <div class="fr-view">
+                        <textarea id="editor_{{ $key }}"
+                                  name="{{ $key }}">{!! $item[$key] ?? $column['default'] !!}</textarea>
+                        {{--<div id="editor_{{ $key }}">{!! $item[$key] ?? $column['default'] !!}</div>--}}
+                    </div>
+                </div>
+            </div>
+            <script>
+
+                var editor_{{ $key }} = new FroalaEditor('#editor_{{ $key }}', {
+                    language: 'zh_cn',
+                    iframe: true,
+                    quickInsertTags: [],
+                    events: {
+                        contentChanged: function () {
+                            $('#editor_{{ $key }}').val(this.html.get());
+                        }
+                    },
+                    // upload image
+                    imageUploadParam: 'file',
+                    imageUploadURL: '{{ $column['uploadURLPath'] }}',
+                    imageUploadMethod: 'POST',
+                    imageInsertButtons: ['imageBack', '|', 'imageUpload', 'imageByURL'],
+                    imageDefaultWidth: 500,
+                    // toolbar buttons
+                    toolbarButtons: ['bold', 'italic', 'underline', 'strikeThrough', '|',
+                        'paragraphFormat', 'fontFamily', 'fontSize', 'textColor', 'backgroundColor', 'clearFormatting', '|',
+                        'align', 'formatOLSimple', 'formatUL', 'outdent', 'indent', 'quote', '|',
+                        'insertLink', 'insertImage', 'insertTable', 'insertHR', '|',
+                        'selectAll', 'clearFormatting', '|',
+                        'undo', 'redo'],
+                    requestWithCORS: true,
+                    requestHeaders: {
+                        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
+                    }
+                });
+
+                /**
+                 tinymce.init({
+                    selector: '#editor_{{ $key }}',
+                    menubar: false,
+                    height: 600,
+                    plugins: [
+                        'advlist autolink link image imagetools lists charmap print preview hr anchor pagebreak spellchecker',
+                        'searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking',
+                        'save table contextmenu directionality emoticons template paste textcolor'
+                    ],
+                    toolbar: 'insertfile undo redo | bold italic underline strikethrough removeformat formats forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image table tabledelete',
+                    images_upload_handler: function (blobInfo, success, failure) {
+                        var xhr, formData;
+                        xhr = new XMLHttpRequest();
+                        xhr.withCredentials = false;
+                        xhr.open('POST', '{{ $column['uploadURLPath'] }}');
+                        var token = '{{ csrf_token() }}';
+                        xhr.setRequestHeader("X-CSRF-TOKEN", token);
+                        xhr.onload = function () {
+                            var json;
+                            if (xhr.status != 200) {
+                                failure('HTTP Error: ' + xhr.status);
+                                return;
+                            }
+                            json = JSON.parse(xhr.responseText);
+
+                            if (!json || typeof json.location != 'string') {
+                                failure('Invalid JSON: ' + xhr.responseText);
+                                return;
+                            }
+                            success(json.location);
+                        };
+                        formData = new FormData();
+                        formData.append('file', blobInfo.blob(), blobInfo.filename());
+                        xhr.send(formData);
+                    },
+                    language: 'zh_CN'
+                });
+                 **/
+                {{--layui.use('layedit', function () {--}}
+                {{--var layedit = layui.layedit;--}}
+                {{--layedit.set({--}}
+                {{--uploadImage: {--}}
+                {{--url: '{{ $column['uploadURLPath'] }}'--}}
+                {{--, acceptMime: 'image/jpg, image/png, image/jpeg'--}}
+                {{--, number: 1--}}
+                {{--, type: 'post' //默认post--}}
+                {{--, headers: {--}}
+                {{--'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')--}}
+                {{--}--}}
+                {{--}--}}
+                {{--, tool: [--}}
+                {{--'undo', 'redo', 'strong', 'italic', 'underline', 'del', 'addhr'--}}
+                {{--, '|', 'fontfamily', 'fontSize', 'fontBackColor', 'colorpicker', 'face'--}}
+                {{--, '|', 'left', 'center', 'right'--}}
+                {{--, '|', 'link', 'unlink', 'image_alt', 'images'--}}
+                {{--, '|', 'table'--}}
+                {{--]--}}
+                {{--});--}}
+                {{--var index = layedit.build('editor_{{ $key }}'); //建立编辑器--}}
+                {{--});--}}
+
+            </script>
+            @break
+
+            @default
+            暂无数据
+        @endswitch
+        @if($hasHr)
+            <hr>
+        @endif
+    @endforeach
+
+    @if(!is_null($footBtns))
+        <hr>
+        <div style="text-align: right">
+            @if(in_array('goback',$footBtns))
+                @if($isAjax)
+                    <button class="layui-btn layui-btn-primary layui-layer-close" style="position:relative;"
+                            type="button">
+                        取消
+                    </button>
+                @else
+                    <button class="layui-btn layui-btn-primary layui-layer-close" style="position:relative;"
+                            type="button"
+                            onclick="javascript:history.go(-1);">返回
+                    </button>
+                @endif
+            @endif
+            @if(in_array('save',$footBtns))
+                <button class="layui-btn" type="submit" lay-submit lay-filter="formBox">保存</button>
+            @endif
+        </div>
+    @endif
+</form>
+
+<script>
+    layui.use(['form', 'laydate', 'table'], function () {
+        var form = layui.form, table = layui.table;
+        form.render();
+
+        form.on('checkbox', function (data) {
+            $(data.othis).toggleClass('layui-form-checked');
+        });
+
+        @if($isAjax)
+        form.on('submit(formBox)', function (data) {
+            var urlPost = $('#form-unify').attr('action');
+            var submitBtn = $(data.elem);
+            submitBtn.addClass('layui-btn-disabled').prop('disabled', true).text('提交中……');
+            $.ajax({
+                url: urlPost,
+                type: 'POST',
+                dataType: 'json',
+                data: data.field
+            })
+                .done(function (res) {
+                    if (res.code === 0) {
+                        submitBtn.text('完成');
+                        layer.msg('完成!', {anim: 0}, function () {
+                            if (res.data.table === '') {
+                                location.reload();
+                            } else {
+                                layer.closeAll();
+                                if (res.data.table !== undefined) {
+                                    table.reload(res.data.table);
+                                }
+                                if (res.url !== undefined) {
+                                    location.href = res.url;
+                                }
+                            }
+                        });
+                    } else {
+                        layer.msg(res.message, {anim: 0}, function () {
+                            submitBtn.removeClass('layui-btn-disabled').prop('disabled', false).text('重新保存');
+                        });
+                    }
+                })
+                .fail(function (res) {
+                    layer.msg(res.message, {anim: 0}, function () {
+                        submitBtn.removeClass('layui-btn-disabled').prop('disabled', false).text('重新保存');
+                    });
+                });
+            return false;
+        });
+        @endif
+    });
+
+    $('.layui-form').on('click', '.layui-close', function () {
+        var self = $(this);
+        self.closest('.imgItem').remove();
+    });
+
+    $('.layui-form').on('click', '.file-delete', function () {
+        var self = $(this);
+        self.closest('tr').remove();
+    });
+
+    $('.date-input').datepicker({
+        language: 'zh-CN',
+        format: 'yyyy-mm-dd',
+        zIndex: 19999999,
+        autoHide: true
+    });
+    $('.dateMonth-input').datepicker({
+        language: 'zh-CN',
+        format: 'yyyy-mm',
+        zIndex: 19999999,
+        autoHide: true
+    });
+    $('.dateYear-input').datepicker({
+        language: 'zh-CN',
+        format: 'yyyy',
+        zIndex: 19999999,
+        autoHide: true
+    });
+</script>
+

+ 387 - 0
Modules/Admin/Resources/views/component/template_table_list.blade.php

@@ -0,0 +1,387 @@
+<div @if(request()->ajax()) style="max-height: 600px;overflow-y: auto;" @endif>
+    @if(count($searchs) > 0)
+        <div class="layui-row">
+            <form class="layui-form" method="get" action="/admin/{{ $path }}" style="margin-bottom: 10px;">
+                @csrf
+                @if(request()->has('id'))
+                    <input type="hidden" name="id" value="{{ request()->input('id') }}">
+                @endif
+                @foreach($searchs as $var => $search)
+                    @if($search['type'] == 'input')
+                        <div class="layui-input-inline">
+                            <input class="layui-input" type="text"
+                                   placeholder="{{ $search['label'] }}"
+                                   name="{{ $var }}"
+                                   value="{{ ${$var} ?? '' }}">
+                        </div>
+                    @endif
+                    @if($search['type'] == 'select')
+                        <div class="layui-input-inline">
+                            <select name="{{ $var }}">
+                                <option value="0"
+                                        @if(!isset($search['assist'])) selected @endif>{{ $search['label'] }}
+                                </option>
+                                @if(count($search['assist']) > 0)
+                                    @foreach($search['assist'] as $k => $col)
+                                        <option value="{{ $k }}"
+                                                @if(isset(${$var}) && ${$var} == $k) selected @endif>{{ $col }}
+                                        </option>
+                                    @endforeach
+                                @endif
+                            </select>
+                        </div>
+                    @endif
+                    @if($search['type'] == 'tree_select')
+                        <div class="layui-input-inline">
+                            <select name="{{ $var }}">
+                                <option value="0"
+                                        @if(!isset($search['assist'])) selected @endif>{{ $search['label'] }}
+                                </option>
+                                @if(count($search['assist']) > 0)
+                                    @include('admin::component.multi_select_option', ['selects' => $search['assist'], 'selectPid' => request($var) ?? ''])
+                                @endif
+                            </select>
+                        </div>
+                    @endif
+                    @if($search['type'] == 'date')
+                        <div class="layui-input-inline">
+                            <input class="layui-input date-{{ $var }}" type="text"
+                                   placeholder="{{ $search['label'] ?? '日期' }}"
+                                   name="{{ $var }}" autocomplete="off" readonly
+                                   disableautocomplete value="{{ $search['assist'][0] ?? '' }}"
+                            >
+                        </div>
+                        <script>
+                            $('.date-{{ $var }}').datepicker({
+                                language: 'zh-CN',
+                                format: 'yyyy-mm-dd',
+                                date: '{{ $search['assist'][0] ?? null }}',
+                            });
+                        </script>
+                    @endif
+                    @if($search['type'] == 'date_time')
+                        <div class="layui-input-inline">
+                            <input class="layui-input star-{{ $var }}" type="text"
+                                   placeholder="{{ $search['label'][0] ?? '起始日期' }}"
+                                   name="star_{{ $var }}" autocomplete="off" readonly
+                                   disableautocomplete value="{{ $search['assist'][0] ?? '' }}">
+                        </div> -
+                        <div class="layui-input-inline">
+                            <input class="layui-input end-{{ $var }}" type="text"
+                                   placeholder="{{ $search['label'][1] ?? '结束日期' }}"
+                                   name="end_{{ $var }}" autocomplete="off" readonly
+                                   disableautocomplete value="{{ $search['assist'][1] ?? '' }}">
+                        </div>
+                        <script>
+                            $('.star-{{ $var }}').datepicker({
+                                language: 'zh-CN',
+                                format: 'yyyy-mm-dd',
+                                date: '{{ $search['assist'][0] ?? null }}',
+                                pick: function (rtime) {
+                                    $('.end-{{ $var }}').datepicker('setStartDate', rtime.date);
+                                }
+                            });
+                            $('.end-{{ $var }}').datepicker({
+                                language: 'zh-CN',
+                                format: 'yyyy-mm-dd',
+                                date: '{{ $search['assist'][0] ?? null }}'
+                            });
+                        </script>
+                    @endif
+                @endforeach
+                <button class="layui-btn" type="submit"><i class="layui-icon">&#xe615;</i></button>
+            </form>
+        </div>
+    @endif
+    @if(count($topActions) > 0 || (isset($topActionOthers) && count($topActionOthers)) > 0)
+        <div class="weadmin-block layui-clear">
+            @if(in_array('goback', $topActions))
+                @if(isset($topActions['href']))
+                    <a class="layui-btn layui-btn-primary layui-layer-close" style="position:relative;"
+                       href="{{ $topActions['href'] }}">返回
+                    </a>
+                @else
+                    <button class="layui-btn layui-btn-primary layui-layer-close" style="position:relative;" type="button"
+                            onclick="javascript:history.go(-1);">返回
+                    </button>
+                @endif
+            @endif
+            @if(checkBtn('/admin/'.$path.'/add', $permissionsList))
+                @if(in_array('add', $topActions))
+                    @if(isset($topActions['add_params']))
+                        <a href="/admin/{{ $path }}/add?{{ $topActions['add_params']}} " class="layui-btn">添加</a>
+                    @else
+                        <a href="/admin/{{ $path }}/add" class="layui-btn">添加</a>
+                    @endif
+                @endif
+            @endif
+
+            @if(checkBtn('/admin/'.$path.'/export', $permissionsList))
+                @if(in_array('export', $topActions))
+                    <a href="/admin/{{ $path }}/export?{{ http_build_query(request()->except('_token')) }}"
+                       class="layui-btn">Excel导出当前页</a>
+                    <a href="/admin/{{ $path }}/export?type=all&{{ http_build_query(request()->except('_token')) }}"
+                       class="layui-btn">Excel导出全部</a>
+                @endif
+            @endif
+
+            @if(checkBtn('/admin/'.$path.'/export_condition', $permissionsList))
+                @if(in_array('export_condition', $topActions))
+                    <button onclick="export_condition()" class="layui-btn">导出</button>
+                @endif
+                    <script>
+                        function export_condition(){
+                            var action = $('.layui-form').attr('action');
+                            var new_action = action+'/export_condition';
+                            $('.layui-form').attr('action',new_action);
+                            $('.layui-form').submit();
+                            $('.layui-form').attr('action',action);
+                        }
+                    </script>
+            @endif
+
+            @if(checkBtn('/admin/'.$path.'/importTemplate', $permissionsList))
+                @if(in_array('importTemplate', $topActions))
+                    <a href="/admin/{{ $path }}/importTemplate" class="layui-btn">下载导入模板</a>
+                @endif
+            @endif
+
+            @if(checkBtn('/admin/'.$path.'/import', $permissionsList))
+                @if(in_array('import', $topActions))
+                    <button type="button" class="layui-btn" id="import">
+                        <i class="layui-icon">&#xe67c;</i>Excel导入
+                    </button>
+                @endif
+            @endif
+            <div style="float: right;">
+                @if(isset($topActionOthers) && count($topActionOthers) > 0)
+                    @foreach($topActionOthers as $topActionOther)
+                        @if(checkBtn('/admin/'.$topActionOther['path'], $permissionsList))
+                            @if(isset($topActionOther['isShow']))
+                                @if(isset($topActionOther['isJump']))
+                                    <button class="layui-btn {{ $topActionOther['class'] }}"
+                                            onclick="jumpBtn(this)"
+                                            data-jumptype="{{ $topActionOther['isJump'] }}"
+                                            data-href="{{ $topActionOther['path'] }}">{{ $topActionOther['name'] }}
+                                    </button>
+                                @else
+                                    <a href="/admin/{{ $topActionOther['path'] }}"
+                                       class="layui-btn {{ $topActionOther['class'] }}">{{ $topActionOther['name'] }}</a>
+                                @endif
+
+                            @endif
+                        @endif
+                    @endforeach
+                @endif
+            </div>
+        </div>
+    @endif
+    <table class="layui-table">
+        <thead>
+        <tr>
+            @foreach($columns as $column)
+                <th>{{ $column['name'] }}</th>
+            @endforeach
+            @if((isset($displayActionOthers) && count($displayActionOthers) > 0) || count($actionBtns) > 0)
+                <th>操作</th>
+            @endif
+        </tr>
+        </thead>
+        <tbody>
+        @if(count($items) > 0)
+            @foreach($items as $item)
+                <tr>
+                    @foreach($columns as $varName => $column)
+                        <td>{!! isset($column['value']) ? $column['value']($item->$varName, $item) : $item->$varName !!}</td>
+                    @endforeach
+                    @if((isset($displayActionOthers) && count($displayActionOthers) > 0) || count($actionBtns) > 0)
+                        <td>
+                            @if(isset($displayActionOthers) && count($displayActionOthers) > 0)
+                                @foreach($displayActionOthers as $displayActionOther)
+                                    @if(checkBtn('/admin/'.$displayActionOther['path'], $permissionsList))
+                                        @if(isset($displayActionOther['isShow']) ? $displayActionOther['isShow']($item) : 1)
+                                            @if(isset($displayActionOther['isJump']))
+                                                <button
+                                                    class="layui-btn layui-btn-xs {{ $displayActionOther['class'] }} @if($displayActionOther['isJump'] == 'uploadimg') uploadimg @endif"
+                                                    onclick="jumpBtn(this)"
+                                                    data-title="{{ $displayActionOther['title'] ?? '' }}"
+                                                    data-jumptype="{{ $displayActionOther['isJump'] }}"
+                                                    data-href="{{ substr($displayActionOther['path'],-1) == '&' ? $displayActionOther['path']:$displayActionOther['path'].'?' }}{{ $primaryKey }}={{ $item->$primaryKey }}">{{ $displayActionOther['name'] }}
+                                                </button>
+                                            @else
+                                                <a href="/admin/{{ substr($displayActionOther['path'],-1) == '&' ? $displayActionOther['path']:$displayActionOther['path'].'?' }}{{ $primaryKey }}={{ $item->$primaryKey }}"
+                                                   class="layui-btn layui-btn-xs {{ $displayActionOther['class'] }}"
+                                                   @if(isset($displayActionOther['fullWin'])) target="_blank" @endif>{{ $displayActionOther['name'] }}</a>
+                                            @endif
+                                        @endif
+                                    @endif
+                                @endforeach
+                            @endif
+                            @if(!is_array($item) || !in_array($item[$displayActions['name']], $displayActions['value']))
+                                @if(checkBtn('/admin/'.$path.'/view', $permissionsList))
+                                    @if(in_array('view', $actionBtns))
+                                        <a href="/admin/{{ $path }}/view?{{ $primaryKey }}={{ $item->$primaryKey }}"
+                                           class="layui-btn layui-btn-normal layui-btn-xs" {{ $actionBtnsAttribute['view'] ?? '' }} >查看</a>
+                                    @endif
+                                @endif
+                                @if(checkBtn('/admin/'.$path.'/edit', $permissionsList))
+                                    @if(in_array('edit', $actionBtns))
+                                        <a href="/admin/{{ $path }}/edit?{{ $primaryKey }}={{ $item->$primaryKey }}"
+                                           class="layui-btn layui-btn-xs" {{ $actionBtnsAttribute['edit'] ?? '' }}>编辑</a>
+                                    @endif
+                                @endif
+                                @if(checkBtn('/admin/'.$path.'/del', $permissionsList))
+                                    @if(in_array('del', $actionBtns))
+                                        <button class="layui-btn layui-btn-xs layui-btn-danger delItem"
+                                                data-itemid="{{ $item->$primaryKey }}" {{ $actionBtnsAttribute['del'] ?? '' }}>
+                                            删除
+                                        </button>
+                                    @endif
+                                @endif
+                            @endif
+                        </td>
+                    @endif
+                </tr>
+            @endforeach
+        @else
+            <tr>
+                <td colspan="{{ count($columns) + 1 }}">暂无数据</td>
+            </tr>
+        @endif
+        </tbody>
+    </table>
+</div>
+@if(method_exists($items, 'links'))
+    {{ $items->appends(request()->except('_token'))->links() }}
+@endif
+
+<script>
+    $(function () {
+        $('.delItem').on('click', function () {
+            var self = $(this);
+            layer.confirm('你确定删除?', function () {
+                layer.closeAll();
+                $.post('/admin/{{ $path }}/del', {"{{ $primaryKey }}": self.data('itemid')}, function (res) {
+                    if (res.code === 0) {
+                        layer.msg('成功!', {anim: 0}, function () {
+                            location.reload();
+                        });
+                    } else {
+                        layer.msg(res.message);
+                    }
+                });
+            });
+        })
+    });
+
+    function jumpBtn(el) {
+        var self = $(el);
+        var path = self.data('href');
+        var type = self.data('jumptype');
+        var jvalue = self.data('value') || '';
+        var title = self.data('title') || '';
+        var text = self.text();
+        if (type === 'confirm') {
+            layer.confirm('确定' + text + '?', function (index) {
+                layer.close(index);
+                $.get('/admin/' + path, function (res) {
+                    if (res.code === 0) {
+                        layer.msg('成功!', {anim: 0}, function () {
+                            location.reload();
+                        });
+                    } else {
+                        layer.msg('失败:' + res.message);
+                    }
+                });
+            });
+        } else if (type === 'uploadimg') {
+
+        } else if (type === 'prompt') {
+            layer.prompt({
+                value: jvalue,
+                title: title,
+            }, function (value, index, elem) {
+                layer.close(index);
+                $.get('/admin/' + path, {newValue: value}, function (res) {
+                    if (res.code === 0) {
+                        layer.msg('成功!', {anim: 0, time: 1000}, function () {
+                            self.text(value).data('value', value);
+                            location.reload();
+                        });
+                    } else {
+                        layer.msg('失败:' + res.message);
+                    }
+                });
+            });
+        } else {
+            $.get('/admin/' + path, function (res) {
+                layer.open({
+                    type: 1,
+                    area: '700px',
+                    offset: '150px',
+                    title: false,
+                    content: res
+                });
+            });
+        }
+    }
+
+    layui.use(['upload', 'form'], function () {
+        var upload = layui.upload, form = layui.form;
+
+        form.on('switch', function (data) {
+            var self = $(data.elem);
+            var path = self.data('href');
+            $.get('/admin/' + path, function (res) {
+                console.log(res);
+                if (res.code === 0) {
+                } else {
+                    layer.msg('失败:' + res.message);
+                }
+            });
+        });
+        //执行实例
+        var uploadInst = upload.render({
+            elem: '#import' //绑定元素
+            , field: 'excel'
+            , exts: 'xls|xlsx|csv'
+            , url: '/admin/{{ $path }}/import' //上传接口
+            , done: function (res) {
+                if (res.code === 0) {
+                    layer.msg('导入成功,加载请稍等待!', {anim: 0}, function () {
+                        location.reload();
+                    });
+                } else {
+                    layer.msg('导入失败,即将跳转到错误信息页。', {anim: 0}, function () {
+                        location.href = '/admin/errorPage';
+                    });
+                }
+            }
+            , error: function (res) {
+                layer.msg(res.message);
+            }
+        });
+
+        //执行实例
+        $('.uploadimg').each(function (index, elem) {
+            upload.render({
+                elem: elem //绑定元素
+                , field: 'img'
+                , url: '/admin/' + $(elem).data('href') //上传接口
+                , done: function (res) {
+                    if (res.code === 0) {
+                        layer.msg('上传成功', {anim: 0}, function () {
+                            location.reload();
+                        });
+                    } else {
+                        layer.msg(res.message);
+                    }
+                }
+                , error: function (res) {
+                    layer.msg(res.message);
+                }
+            });
+        });
+
+    });
+</script>

+ 35 - 0
Modules/Admin/Resources/views/component/template_table_view.blade.php

@@ -0,0 +1,35 @@
+<style>
+    .layui-table th {
+        color: #666;
+        text-align: right;
+        background-color: #f2f2f2;
+    }
+</style>
+<div @if(request()->ajax()) style="padding:10px 20px;" @endif>
+    @if(isset($title) && $title)
+        <h2>{{ $title }}
+            @if(!request()->ajax())
+                <button class="layui-btn layui-btn-primary layui-layer-close" style="position:relative;" type="button"
+                        onclick="javascript:history.go(-1);">返回
+                </button>
+            @endif
+        </h2>
+        <hr>
+    @endif
+    <table class="layui-table">
+        @foreach($columns as $key => $column)
+            <tr>
+                <th style="width: 200px;">{{ $column['name'] }}</th>
+                <td>{!! isset($column['value']) ? $column['value']($items[$key]) : $items[$key] !!}</td>
+            </tr>
+        @endforeach
+    </table>
+
+    @if(!request()->ajax())
+        <hr>
+        <button class="layui-btn layui-btn-primary layui-layer-close" style="position:relative;" type="button"
+                onclick="javascript:history.go(-1);">返回
+        </button>
+    @endif
+</div>
+

+ 37 - 0
Modules/Admin/Resources/views/component/template_tree_item.blade.php

@@ -0,0 +1,37 @@
+@foreach($items as $item)
+    <tr>
+        @foreach($columns as $key => $column)
+            @if($key == 'title')
+                <td>
+                    <span class="branch tier{{ $item['tier'] }}"><i></i></span>
+                    @if(isset($item['icon']))
+                        <i class="layui-icon layui-icon-{{ $item['icon'] }}"></i>
+                    @endif
+                    {{ $item['title'] }}
+                </td>
+            @else
+                <td>{!! isset($column['value']) ? $column['value']($item[$key],$item) : $item[$key] !!}</td>
+            @endif
+        @endforeach
+        <td>
+            @if(checkBtn('/admin/'.$path.'/edit', $permissionsList))
+                @if(in_array('edit', $actionBtns))
+                    <button class="layui-btn layui-btn-xs editItem" data-itemid="{{ $item['id'] }}">编辑
+                    </button>
+                @endif
+            @endif
+            @if(checkBtn('/admin/'.$path.'/del', $permissionsList))
+                @if(in_array('del', $actionBtns))
+                    @if(isset($item['can_del']) && $item['can_del'])
+                        <button class="layui-btn layui-btn-xs layui-btn-danger delItem" data-itemid="{{ $item['id'] }}">
+                            删除
+                        </button>
+                    @endif
+                @endif
+            @endif
+        </td>
+    </tr>
+    @if(isset($item['child']) && count($item['child']) > 0)
+        @include('admin::component.template_tree_item', ['items' => $item['child'], 'columns' => $columns])
+    @endif
+@endforeach

+ 224 - 0
Modules/Admin/Resources/views/component/template_tree_list.blade.php

@@ -0,0 +1,224 @@
+<div class="layui-row">
+    @if(checkBtn('/admin/'.$path.'/add', $permissionsList))
+        <button class="layui-btn" onclick="addItem()"><i class="layui-icon"></i>增加</button>
+    @endif
+    <div style="float: right;">
+        @if(isset($displayActionOthers) && count($displayActionOthers) > 0)
+            @foreach($displayActionOthers as $displayActionOther)
+                @if(checkBtn('/admin/'.$displayActionOther['path'], $permissionsList))
+                    @if(isset($displayActionOther['isShow']))
+                        @if(isset($displayActionOther['isJump']))
+                            <button class="layui-btn {{ $displayActionOther['class'] }}" onclick="jumpBtn(this)"
+                                    data-jumptype="{{ $displayActionOther['isJump'] }}"
+                                    data-href="{{ $displayActionOther['path'] }}">{{ $displayActionOther['name'] }}
+                            </button>
+                        @else
+                            <a href="/admin/{{ $displayActionOther['path'] }}"
+                               class="layui-btn {{ $displayActionOther['class'] }}">{{ $displayActionOther['name'] }}</a>
+                        @endif
+
+                    @endif
+                @endif
+            @endforeach
+        @endif
+        @if(checkBtn('/admin/'.$path.'/export', $permissionsList))
+            @if(in_array('export', $topActions))
+                {{--                <a href="/admin/{{ $path }}/export?{{ http_build_query(request()->except('_token')) }}"--}}
+                {{--                   class="layui-btn">Excel导出当前页</a>--}}
+                <a href="/admin/{{ $path }}/export?type=all&{{ http_build_query(request()->except('_token')) }}"
+                   class="layui-btn">Excel导出全部</a>
+            @endif
+        @endif
+
+        @if(checkBtn('/admin/'.$path.'/importTemplate', $permissionsList))
+            @if(in_array('importTemplate', $topActions))
+                <a href="/admin/{{ $path }}/importTemplate" class="layui-btn">下载导入模板</a>
+            @endif
+        @endif
+
+        @if(checkBtn('/admin/'.$path.'/import', $permissionsList))
+            @if(in_array('import', $topActions))
+                <button type="button" class="layui-btn" id="import">
+                    <i class="layui-icon">&#xe67c;</i>Excel导入
+                </button>
+            @endif
+        @endif
+    </div>
+</div>
+
+<table class="layui-table">
+    <thead>
+    <tr>
+        @foreach($columns as $column)
+            <th>{{ $column['name'] }}</th>
+        @endforeach
+        <th>操作</th>
+    </tr>
+    </thead>
+    <tbody>
+    @if(count($items) > 0)
+        @include('admin::component.template_tree_item', ['items' => $items, 'columns' => $columns, 'actionBtns' => $actionBtns,'path' => $path])
+    @endif
+    </tbody>
+</table>
+
+<script>
+    $(function () {
+        editItem();
+        delItem();
+    });
+
+    function addItem() {
+        $.get('/admin/{{ $path }}/add', function (res) {
+            layer.open({
+                type: 1,
+                area: '700px',
+                title: false,
+                content: res
+            })
+        });
+
+    }
+
+    function editItem() {
+        $('.editItem').on('click', function () {
+            var self = $(this);
+            $.get('/admin/{{ $path }}/edit', {id: self.data('itemid')}, function (res) {
+                layer.open({
+                    type: 1,
+                    area: '700px',
+                    title: false,
+                    content: res
+                });
+            });
+        })
+
+    }
+
+    function delItem() {
+        $('.delItem').on('click', function () {
+            var self = $(this);
+            layer.confirm('你确定删除?', function () {
+                $.post('/admin/{{ $path }}/del', {id: self.data('itemid')}, function (res) {
+                    console.log(res);
+                    if (res.code === 0) {
+                        layer.msg('完成!', {anim: 0}, function () {
+                            location.reload();
+                        });
+                    }
+                });
+            });
+
+        })
+
+    }
+
+    function jumpBtn(el) {
+        var self = $(el);
+        var path = self.data('href');
+        var type = self.data('jumptype');
+        var jvalue = self.data('value') || '';
+        var text = self.text();
+        if (type === 'confirm') {
+            layer.confirm('确定' + text + '?', function (index) {
+                layer.close(index);
+                $.get('/admin/' + path, function (res) {
+                    if (res.code === 0) {
+                        layer.msg('成功!', {anim: 0}, function () {
+                            location.reload();
+                        });
+                    } else {
+                        layer.msg('失败:' + res.message);
+                    }
+                });
+            });
+        } else if (type === 'uploadimg') {
+
+        } else if (type === 'prompt') {
+            layer.prompt({
+                value: jvalue,
+                title: '请输入排序',
+            }, function (value, index, elem) {
+                layer.close(index);
+                $.get('/admin/' + path, {newValue: value}, function (res) {
+                    if (res.code === 0) {
+                        layer.msg('成功!', {anim: 0, time: 1000}, function () {
+                            self.text(value).data('value', value);
+                        });
+                    } else {
+                        layer.msg('失败:' + res.message);
+                    }
+                });
+            });
+        } else {
+            $.get('/admin/' + path, function (res) {
+                console.log(res);
+                if (res.code === 0) {
+                    layer.msg('完成!', {anim: 0}, function () {
+                        location.reload();
+                    });
+                }
+            });
+        }
+    }
+
+    layui.use(['upload', 'form'], function () {
+        var upload = layui.upload, form = layui.form;
+
+        form.on('switch', function (data) {
+            var self = $(data.elem);
+            var path = self.data('href');
+            $.get('/admin/' + path, function (res) {
+                console.log(res);
+                if (res.code === 0) {
+                    location.reload();
+                } else {
+                    layer.msg('失败:' + res.message);
+                }
+            });
+        });
+
+        //执行实例
+        var uploadInst = upload.render({
+            elem: '#import' //绑定元素
+            , field: 'excel'
+            , exts: 'xls|xlsx|csv'
+            , url: '/admin/{{ $path }}/import' //上传接口
+            , done: function (res) {
+                if (res.code === 0) {
+                    layer.msg('导入成功,加载请稍等待!', {anim: 0}, function () {
+                        location.reload();
+                    });
+                } else {
+                    layer.msg('导入失败,即将跳转到错误信息页。', {anim: 0}, function () {
+                        location.href = '/admin/errorPage';
+                    });
+                }
+            }
+            , error: function (res) {
+                layer.msg(res.message);
+            }
+        });
+
+        //执行实例
+        $('.uploadimg').each(function (index, elem) {
+            upload.render({
+                elem: elem //绑定元素
+                , field: 'img'
+                , url: '/admin/' + $(elem).data('href') //上传接口
+                , done: function (res) {
+                    if (res.code === 0) {
+                        layer.msg('上传成功', {anim: 0}, function () {
+                            location.reload();
+                        });
+                    } else {
+                        layer.msg(res.message);
+                    }
+                }
+                , error: function (res) {
+                    layer.msg(res.message);
+                }
+            });
+        });
+    });
+</script>

+ 9 - 0
Modules/Admin/Resources/views/index.blade.php

@@ -0,0 +1,9 @@
+@extends('admin::layouts.master')
+
+@section('content')
+    <h1>Hello World</h1>
+
+    <p>
+        This view is loaded from module: {!! config('admin.name') !!}
+    </p>
+@endsection

+ 20 - 0
Modules/Admin/Resources/views/layouts/error.blade.php

@@ -0,0 +1,20 @@
+@if($time > 0)
+    <h3>错误:{{ $msg }}</h3>
+    <p>页面将在 <span id="error">{{ $time }}</span> 秒后跳转</p>
+
+    <script type="text/javascript">
+        var t = {{ $time }};//设定跳转的时间
+        setInterval("refer()", 1000); //启动1秒定时
+        function refer() {
+            if (t == 0) {
+                location.href = '{{ $url }}'; //跳转的地址
+            }
+            $('#error').text(t);
+            t--; // 计数器递减
+        }
+    </script>
+@else
+    <h3>错误信息:</h3>
+    <div>{!! $msg !!}</div>
+    <p>返回上级页面请点击 ——> <a href="{{ $url }}">这里</a></p>
+@endif

+ 273 - 0
Modules/Admin/Resources/views/layouts/master.blade.php

@@ -0,0 +1,273 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="renderer" content="webkit|ie-comp|ie-stand">
+    <meta name="csrf-token" content="{{ csrf_token() }}">
+    {{--<title>{{ $setting['admintitle'] ?? '后台管理' }}</title>--}}
+    <title>后台管理</title>
+    <meta name="renderer" content="webkit">
+    <meta name="description" content="">
+    <meta name="keywords" content="">
+    <link rel="shortcut icon" href="/favicon.png" type="image/x-icon">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta http-equiv="Cache-Control" content="no-siteapp"/>
+    <link rel="stylesheet" href="/css/admin/font.css">
+    <link rel="stylesheet" href="/css/admin/weadmin.css">
+    {{--<link rel="stylesheet" href="/qrcode/static/css/style.css">--}}
+    <script src="/js/jquery.min.js"></script>
+    <script src="/js/admin/js.cookie.js"></script>
+    <script src="/layui/layui.js" charset="utf-8"></script>
+    <script src="/js/admin/datepicker.min.js"></script>
+    <script src="/js/admin/datepicker.zh-CN.js"></script>
+    {{-- Laravel Mix - CSS File --}}
+{{--    <link rel="stylesheet" href="{{ mix('css/admin/public.css') }}">--}}
+    <link rel="stylesheet" href="/css/admin/public.css">
+    <style>
+        #welcomeTab i {
+            display: none;
+        }
+
+        .layui-btn-normal {
+            background-color: #52c41a;
+        }
+
+        .layui-btn-danger {
+            background-color: #f5222d;
+        }
+
+        .layui-btn-default {
+            border: 1px solid #C9C9C9;
+            background-color: #fff;
+            color: #555;
+        }
+
+        .layui-btn-default:hover {
+            border-color: #2d6dcc;
+            color: #2d6dcc;
+        }
+
+        .layui-layer-close {
+            background-color: #fff;
+        }
+
+        .layui-btn-disabled, .layui-btn-disabled:active, .layui-btn-disabled:hover {
+            border: 1px solid #e6e6e6;
+            background-color: #FBFBFB;
+            color: #C9C9C9;
+            cursor: not-allowed;
+            opacity: 1;
+        }
+
+        #top .layui-nav .layui-btn {
+            background-color: #03152A;
+        }
+
+        .layui-nav-bar {
+            background-color: #3B91FF;
+        }
+
+        #nav li:hover > a {
+            color: #fff;
+        }
+    </style>
+</head>
+<body>
+<!-- 顶部开始 -->
+<div id="top" class="container" style="background-color: #03152A;">
+    <div class="logo">
+{{--        <a href="./index.html"><img src="/favicon.png" alt="">{{ $setting['admintitle'] ?? '后台管理' }}</a>--}}
+        <a href="./index.html"><img src="/favicon.png" alt="">后台管理</a>
+    </div>
+    <div class="left_open">
+        <!-- <i title="展开左侧栏" class="iconfont">&#xe699;</i> -->
+        <i title="展开左侧栏" class="layui-icon layui-icon-shrink-right"></i>
+
+    </div>
+    <ul class="layui-nav right" lay-filter="">
+        <li class="layui-nav-item">
+            <button onclick="viewClear()" class="layui-btn">清除缓存</button>
+        </li>
+        <li class="layui-nav-item" style="display: none;">
+            {{--<button onclick="TopTabMenu('详细资料','/admin/welcome/userinfo?staff_num={{ $user->staff_num }}','userInfo')"--}}
+                    {{--class="layui-btn">我的消息--}}
+            {{--</button>--}}
+            <button onclick="TopTabMenu('详细资料','/admin/welcome/userinfo?staff_num=','userInfo')"
+                    class="layui-btn">我的消息
+            </button>
+        </li>
+        <li class="layui-nav-item">
+            <input type="hidden" id="userStaffNum" value="{{ $user->staff_num }}">
+            <a href="javascript:;">{{ $user->name }}</a>
+            <dl class="layui-nav-child">
+                <!-- 二级菜单 -->
+                {{--@if($user->staff_num != 'admin')--}}
+                    {{--@if(checkBtn('/admin/welcome/userinfo', $permissionsList))--}}
+                        {{--<dd>--}}
+                            {{--<a href="javascript:TopTabMenu('详细资料','/admin/welcome/userinfo?staff_num={{ $user->staff_num }}','userInfo');">详细资料</a>--}}
+                        {{--</dd>--}}
+                    {{--@endif--}}
+                    {{--@if(checkBtn('/admin/dashboard/myfiles/list', $permissionsList))--}}
+                        {{--<dd>--}}
+                            {{--<a href="javascript:TopTabMenu('我的文档','/admin/dashboard/myfiles/list','myFiles');">我的文档</a>--}}
+                        {{--</dd>--}}
+                    {{--@endif--}}
+                    {{--@if(checkBtn('/admin/dashboard/sign/update', $permissionsList))--}}
+                        {{--<dd>--}}
+                            {{--<a href="javascript:signUpdate();">我的签名</a>--}}
+                        {{--</dd>--}}
+                    {{--@endif--}}
+                {{--@endif--}}
+                <dd>
+                    <a href="javascript:resetPassword();">修改密码</a>
+                </dd>
+                <dd>
+                    <a class="loginout" href="/admin/logout">退出</a>
+                </dd>
+            </dl>
+        </li>
+    </ul>
+
+</div>
+<!-- 顶部结束 -->
+<!-- 中部开始 -->
+<!-- 左侧菜单开始 -->
+<div class="left-nav">
+    <div id="side-nav">
+        <ul id="nav">
+            @include('admin::component.side_menu', ['menus' => $menus, 'tier' => 1])
+        </ul>
+    </div>
+</div>
+<!-- <div class="x-slide_left"></div> -->
+<!-- 左侧菜单结束 -->
+<!-- 右侧主体开始 -->
+<div class="page-content">
+    <div class="layui-tab tab" lay-filter="wenav_tab" id="WeTabTip" lay-allowclose="true">
+        <ul class="layui-tab-title" id="tabName">
+            <li id="welcomeTab">首页</li>
+        </ul>
+        <div class="layui-tab-content">
+            <div class="layui-tab-item layui-show">
+                <iframe
+                        src=@if(request()->has('category')) '/admin/welcome?category={{request()->input("category")}}' @else
+                    '/admin/welcome' @endif
+                frameborder="0" scrolling="yes" class="weIframe"></iframe>
+            </div>
+        </div>
+    </div>
+</div>
+<div class="page-content-bg"></div>
+<!-- 右侧主体结束 -->
+<!-- 中部结束 -->
+<!-- 底部开始 -->
+<div class="footer">
+    <div class="copyright">Copyright ©2018 WeAdmin v1.0 All Rights Reserved</div>
+</div>
+<!-- 底部结束 -->
+<script type="text/javascript">
+    Cookies.remove('isIframe');
+    //			layui扩展模块的两种加载方式-示例
+    //		    layui.extend({
+    //			  admin: '{/}../../static/js/admin' // {/}的意思即代表采用自有路径,即不跟随 base 路径
+    //			});
+    //			//使用拓展模块
+    //			layui.use('admin', function(){
+    //			  var admin = layui.admin;
+    //			});
+    $.ajaxSetup({
+        cache: false,
+        headers: {
+            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
+        },
+        xhrFields: {
+            withCredentials: true
+        },
+        beforeSend: function () {  // 请求发送前通用程序
+            gload = layer.load(3, {shade: 0.3});
+        },
+        complete: function (res) {  // 请求发送结束后通用程序
+            layer.close(gload);
+            //登陆过期,则跳转到登录页面
+            if (res.status == 401) {
+                layer.alert('登陆超时了,您将跳转到登陆页!', function () {
+                    location.href = '/admin/login';
+                });
+            }
+        }
+    });
+    layui.config({
+        base: '/js/admin/'
+        , version: '101100'
+    }).use('admin');
+    layui.use(['jquery', 'admin'], function () {
+        var $ = layui.jquery;
+        $(function () {
+            var login = JSON.parse(localStorage.getItem("login"));
+            if (login) {
+                if (login = 0) {
+                    window.location.href = '/admin/login';
+                    return false;
+                } else {
+                    return false;
+                }
+            } else {
+                window.location.href = '/admin/login';
+                return false;
+            }
+        });
+
+
+    });
+
+    function resetPassword() {
+        $.get('/admin/welcome/resetpassword', {id: {{ $user->id }} }, function (res) {
+            layer.open({
+                type: 1,
+                area: '700px',
+                title: false,
+                content: res
+            });
+        });
+    }
+
+    function signUpdate() {
+        $.get('/admin/dashboard/sign', function (res) {
+            layer.open({
+                type: 1,
+                area: '700px',
+                title: false,
+                content: res
+            });
+        });
+    }
+
+    function viewClear() {
+        $.get('/admin/file/view/clear', function (res) {
+            if (res.code === 0) {
+                layer.msg('完成!', {anim: 0}, function () {
+                    location.reload();
+                });
+            }
+        });
+    }
+
+    function getUserStaffNum() {
+        return $('#userStaffNum').val();
+    }
+
+</script>
+{{-- Laravel Mix - JS File --}}
+{{--<script src="{{ mix('js/admin/public.js') }}"></script>--}}
+<script src="/js/admin/public.js"></script>
+</body>
+
+<!--Tab菜单右键弹出菜单-->
+<ul class="rightMenu" id="rightMenu">
+    <li data-type="fresh">刷新</li>
+    <li data-type="current">关闭当前</li>
+    <li data-type="other">关闭其它</li>
+    <li data-type="all">关闭所有</li>
+</ul>
+</html>

+ 168 - 0
Modules/Admin/Resources/views/layouts/sub.blade.php

@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="csrf-token" content="{{ csrf_token() }}">
+    <title>后台管理</title>
+    <meta name="renderer" content="webkit|ie-comp|ie-stand">
+    <meta name="description" content="">
+    <meta name="keywords" content="">
+    <link rel="shortcut icon" href="/favicon.png" type="image/x-icon">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta http-equiv="Cache-Control" content="no-siteapp"/>
+    <link rel="stylesheet" href="/css/admin/font.css">
+    <link rel="stylesheet" href="/css/admin/weadmin.css">
+    <link rel="stylesheet" href="/css/admin/datepicker.min.css">
+    <link rel="stylesheet" href="/layui/css/formSelects-v4.css">
+    {{--<link rel="stylesheet" href="/qrcode/static/css/style.css">--}}
+    <link rel="stylesheet" href="/wangedit/wangEditor.min.css">
+    <link rel="stylesheet" href="/froala_editor/css/froala_editor.pkgd.min.css">
+
+    <script src="/js/jquery.min.js"></script>
+    <script src="/layui/layui.js" charset="utf-8"></script>
+    <script src="/js/admin/datepicker.min.js"></script>
+    <script src="/js/admin/datepicker.zh-CN.js"></script>
+    <script src="/wangedit/wangEditor.min.js"></script>
+    <script src="/froala_editor/js/froala_editor.pkgd.min.js"></script>
+    <script src="/froala_editor/js/languages/zh_cn.js"></script>
+    <script src="/js/tinymce/tinymce.min.js"></script>
+
+    {{-- Laravel Mix - CSS File --}}
+    {{--    <link rel="stylesheet" href="{{ mix('css/admin/public.css') }}">--}}
+    <link rel="stylesheet" href="/css/admin/public.css">
+    <style>
+        .layui-btn-normal {
+            background-color: #52c41a;
+        }
+
+        .layui-btn-danger {
+            background-color: #f5222d;
+        }
+
+        .layui-btn-default {
+            border: 1px solid #C9C9C9;
+            background-color: #fff;
+            color: #555;
+        }
+
+        .layui-btn-default:hover {
+            border-color: #2d6dcc;
+            color: #2d6dcc;
+        }
+
+        .layui-layer-close {
+            background-color: #fff;
+        }
+
+        .layui-btn-disabled, .layui-btn-disabled:active, .layui-btn-disabled:hover {
+            border: 1px solid #e6e6e6;
+            background-color: #FBFBFB;
+            color: #C9C9C9;
+            cursor: not-allowed;
+            opacity: 1;
+        }
+
+        .layui-form-checked span, .layui-form-checked:hover span {
+            color: #fff;
+            background-color: #2d6dcc;
+        }
+
+        .layui-form-checked i, .layui-form-checked:hover i {
+            color: #2d6dcc;
+        }
+
+        .xm-select-parent .xm-form-select dl {
+            z-index: 19891116;
+        }
+
+        .layui-layer.layui-layer-page .layui-layer-content {
+            overflow: inherit;
+        }
+
+        .layui-table td {
+            max-width: 600px;
+            word-wrap: break-word;
+        }
+    </style>
+</head>
+
+<body>
+<div class="weadmin-nav">
+	<span class="layui-breadcrumb">
+        @include('admin::component.breadcrumb', ['menus' => $menus, 'num' => 0])
+    </span>
+    <a class="layui-btn layui-btn-sm" style="line-height:1.6em;margin-top:3px;float:right"
+       href="javascript:location.replace(location.href);" title="刷新">
+        <i class="layui-icon" style="line-height:30px">ဂ</i></a>
+</div>
+<div class="weadmin-body">
+    {!! $content !!}
+</div>
+</body>
+<script>
+    var gload = '';
+
+    $.ajaxSetup({
+        cache: false,
+        headers: {
+            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
+        },
+        xhrFields: {
+            withCredentials: true
+        },
+        beforeSend: function () {  // 请求发送前通用程序
+            gload = layer.load(3, {shade: 0.3});
+        },
+        complete: function (res) {  // 请求发送结束后通用程序
+            layer.close(gload);
+            //登陆过期,则跳转到登录页面
+            if (res.status == 401) {
+                layer.alert('登陆超时了,您将跳转到登陆页!', function () {
+                    location.href = '/admin/login';
+                });
+            }
+        }
+    });
+    layui.extend({
+        admin: '/js/admin/admin',
+        formSelects: '/layui/extends/formSelects-v4.min',
+    });
+    layui.use(['admin', 'form'], function () {
+        var admin = layui.admin, form = layui.form;
+        form.on('select', function (data) {
+            // console.log(data.elem); //得到select原始DOM对象
+            // console.log(data.value); //得到被选中的值
+            // console.log(data.othis); //得到美化后的DOM对象
+            var old_value = data.othis.find('input').val();
+            data.othis.find('input').val(old_value.trim());
+        });
+        // if ($('.layui-input.layui-unselect').val() !== undefined) {
+        //     $('.layui-input.layui-unselect').val($('.layui-input.layui-unselect').val().trim());
+        // }
+        $('.layui-input.layui-unselect').each(function () {
+            var self = $(this);
+            if (self.val() !== undefined) {
+                self.val(self.val().trim());
+            }
+        });
+
+        $('body').on('click', '.weAdminEdit', function () {
+            var self = $(this);
+            WeAdminEdit(self.attr('href'), self.text());
+            return false;
+        })
+
+        $('body').on('click', '.newWindow', function () {
+            var self = $(this);
+            window.open(self.attr('href'), '_blank');
+            return false;
+        })
+    });
+    $('body').on('click', '.layui-unselect.layui-form-checkbox', function () {
+        var self = $(this);
+        self.toggleClass('layui-form-checked');
+    })
+
+</script>
+</html>

+ 16 - 0
Modules/Admin/Resources/views/layouts/success.blade.php

@@ -0,0 +1,16 @@
+<h3>成功!</h3>
+<p>页面将在 <span id="success">{{ $time }}</span> 秒后跳转</p>
+
+
+<script type="text/javascript">
+    var t = {{ $time }};//设定跳转的时间
+    setInterval("refer()", 1000); //启动1秒定时
+    function refer() {
+        if (t == 0) {
+            location.href = '{{ $url }}'; //跳转的地址
+        }
+        $('#success').text(t);
+        t--; // 计数器递减
+    }
+</script>
+

+ 193 - 0
Modules/Admin/Resources/views/login.blade.php

@@ -0,0 +1,193 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="csrf-token" content="{{ csrf_token() }}">
+    <meta name="viewport"
+          content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+    <title>后台管理</title>
+    <meta name="renderer" content="webkit|ie-comp|ie-stand">
+    <meta name="description" content="">
+    <meta name="keywords" content="">
+    <link rel="shortcut icon" href="/favicon.png" type="image/x-icon">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta http-equiv="Cache-Control" content="no-siteapp"/>
+    <link rel="stylesheet" href="/css/admin/font.css">
+    <link rel="stylesheet" href="/css/admin/weadmin.css">
+    <script src="/js/jquery.min.js"></script>
+    <script src="/js/admin/js.cookie.js"></script>
+    <script src="/layui/layui.js" charset="utf-8"></script>
+    <style>
+        .login input.layui-btn-disabled, .login input.layui-btn-disabled:active, .login input.layui-btn-disabled:hover {
+            border: 1px solid #e6e6e6;
+            background-color: #FBFBFB;
+            color: #C9C9C9;
+            cursor: not-allowed;
+            opacity: 1;
+        }
+
+        .login-bg {
+            background-image: url('/images/login_bg.jpg');
+        }
+
+        .login {
+            min-height: 990px;
+            max-width: 990px;
+            padding: 0;
+            background-color: transparent;
+            margin-top: 10%;
+        }
+
+        .login .message {
+            margin: 40px 0 0;
+            padding: 0 20px;
+            background: transparent;
+            position: relative;
+            color: #fff;
+            font-size: 16px;
+            text-align: center;
+        }
+
+        .login .message h1 {
+            font-size: 72px;
+        }
+
+        .login .message p {
+            font-size: 42px;
+            margin-top: 30px;
+        }
+
+        .login input[type=text], .login input[type=password] {
+            width: 400px;
+            height: 60px;
+            font-size: 20px;
+            color: #555;
+            padding: 0 46px;
+            margin-top: 30px;
+            border-radius: 60px;
+        }
+
+        .login input[type=text]::-webkit-input-placeholder, .login input[type=password]::-webkit-input-placeholder {
+            color: #BDC3C7;
+        }
+
+        .login input[type=text]::-moz-placeholder, .login input[type=password]::-moz-placeholder { /* Mozilla Firefox 19+ */
+            color: #BDC3C7;
+        }
+
+        .login input[type=text]:-moz-placeholder, .login input[type=password]:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
+            color: #BDC3C7;
+        }
+
+        .login input[type=text]:-ms-input-placeholder, .login input[type=password]:-ms-input-placeholder { /* Internet Explorer 10-11 */
+            color: #BDC3C7;
+        }
+
+        .login input[type=submit] {
+            width: 220px;
+            height: 70px;
+            font-size: 32px;
+            font-weight: bold;
+            color: #2C3E50;
+            background-color: #fff;
+            margin: 40px 0 0 100px;
+            border-radius: 70px;
+        }
+
+        .form-line {
+            position: relative;
+        }
+
+        .form-line span {
+            width: 33px;
+            top: 16px;
+            right: 40px;
+            position: absolute;
+        }
+    </style>
+</head>
+
+<body class="login-bg">
+
+<div class="login">
+    <div class="message">
+        <h1>智慧矿山</h1>
+        <p>智慧矿山视频管理系统</p>
+    </div>
+
+    <form method="post" class="layui-form" style="width: 400px;margin:60px auto 0;">
+        @csrf
+        <div class="form-line">
+            <input name="staff_num" placeholder="工号" type="text" lay-verify="required" class="layui-input">
+            <span><img src="/images/staff_num.png" alt=""></span>
+        </div>
+        <div class="form-line">
+            <input name="password" lay-verify="required" placeholder="密码" type="password" class="layui-input">
+            <span><img src="/images/password.png" alt=""></span>
+        </div>
+        <input class="loginin" value="登 陆" lay-submit lay-filter="login" type="submit">
+    </form>
+</div>
+
+<script type="text/javascript">
+    if (!Cookies.get('isIframe')) {
+        Cookies.set('isIframe', true);
+        parent.parent.location.reload();
+    }
+
+    layui.extend({
+        admin: '/js/admin/admin'
+    });
+    layui.use(['form', 'admin'], function () {
+        var form = layui.form
+            , admin = layui.admin;
+
+        //监听提交
+        function btoaEnhanced(str) {
+            return btoa(unescape(encodeURIComponent(str)));
+        }
+
+        function atobEnhanced(str) {
+            return decodeURIComponent(escape(atob(str)));
+        }
+
+        form.on('submit(login)', function (data) {
+            $('.loginin').addClass('layui-btn-disabled').prop('disabled', true).val('登陆中……');
+            $.ajax({
+                type: 'POST',
+                url: '/admin/login',
+                data: {staff_num: data.field.staff_num, password: btoaEnhanced(data.field.password)},
+                headers: {
+                    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
+                },
+                success: function (res) {
+                    if (res.code === 0) {
+                        layer.msg(res.message, {anim: 0}, function () {
+                            location.href = '/admin';
+                        });
+                    } else {
+                        layer.msg(res.message, {anim: 0}, function () {
+                            location.reload();
+                        });
+                    }
+                },
+                error: function (res) {
+                    console.log(res.responseJSON);
+                    layer.msg(res.responseJSON.errors.staff_num[0]);
+                },
+                complete: function () {
+                    $('.loginin').removeClass('layui-btn-disabled').prop('disabled', false).val('登 陆');
+                }
+            });
+            return false;
+        });
+    });
+</script>
+<!-- 底部结束 -->
+
+</body>
+
+<script>
+
+</script>
+</html>

+ 91 - 0
Modules/Admin/Resources/views/roles.blade.php

@@ -0,0 +1,91 @@
+<h2>{{ $title }} <a href="javascript:history.go(-1);" class="layui-btn layui-btn-primary layui-layer-close"
+                    style="position:relative;">返回</a></h2>
+<hr/>
+
+<form class="layui-form">
+    <div class="layui-form-item">
+         <input type="hidden" name="staff_num" id="staff_num" value="{{ $staff_num }}">
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label">全部选择</label>
+        <div class="layui-input-block">
+            <input type="checkbox" lay-filter="xuanze" lay-skin="switch" lay-text="全选|全不选">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label">选择权限</label>
+        <div class="layui-input-block">
+            <div id="LAY-auth-tree-index"></div>
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <div class="layui-input-block">
+            <button class="layui-btn" type="submit" lay-submit lay-filter="LAY-auth-tree-submit">提交</button>
+            <button class="layui-btn layui-btn-default" type="reset">重置</button>
+        </div>
+    </div>
+</form>
+
+<script type="text/javascript">
+    layui.extend({
+        authtree: '/js/admin/layui/extends/authtree',
+    });
+    layui.use(['jquery', 'authtree', 'form', 'layer'], function () {
+        var $ = layui.jquery;
+        var authtree = layui.authtree;
+        var form = layui.form;
+        var layer = layui.layer;
+        // 初始化
+        var trees = authtree.listConvert(@json($menusAll), {
+            primaryKey: 'id'
+            , startPid: 0
+            , parentKey: 'parent_id'
+            , nameKey: 'title'
+            , valueKey: 'id'
+            , checkedKey: eval(<?php echo json_encode($checkedId);?>)
+        });
+
+        // 渲染时传入渲染目标ID,树形结构数据(具体结构看样例,checked表示默认选中),以及input表单的名字
+        authtree.render('#LAY-auth-tree-index', trees, {
+            inputname: 'authids[]'
+            , layfilter: 'lay-check-auth'
+            // ,autoclose: false
+            // ,autochecked: false
+            // ,openchecked: true
+            , openall: true
+            , autowidth: true
+        });
+
+        form.on('switch(zhankai)', function (data) {
+            if (data.elem.checked) {
+                authtree.showAll('#LAY-auth-tree-index');
+            } else {
+                authtree.closeAll('#LAY-auth-tree-index');
+            }
+        });
+
+        form.on('switch(xuanze)', function (data) {
+            if (data.elem.checked) {
+                authtree.checkAll('#LAY-auth-tree-index');
+            } else {
+                authtree.uncheckAll('#LAY-auth-tree-index');
+            }
+        });
+
+        form.on('submit(LAY-auth-tree-submit)', function (obj) {
+            var authids = authtree.getChecked('#LAY-auth-tree-index');
+            console.log('Choosed authids is', authids);
+            var staff_num = $('#staff_num').val();
+            $.post('/admin/users/roles/edit',{'staff_num':staff_num,'mine_id':authids},function(res){
+                if (res.code === 0) {
+                    layer.msg('提交成功!');
+                    location.href = '/admin/users/list';
+                }
+            })
+            return false;
+        });
+
+    });
+
+</script>

+ 0 - 0
Modules/Admin/Routes/.gitkeep


+ 23 - 0
Modules/Admin/Routes/api.php

@@ -0,0 +1,23 @@
+<?php
+
+use Illuminate\Http\Request;
+
+/*
+|--------------------------------------------------------------------------
+| API Routes
+|--------------------------------------------------------------------------
+|
+| Here is where you can register API routes for your application. These
+| routes are loaded by the RouteServiceProvider within a group which
+| is assigned the "api" middleware group. Enjoy building your API!
+|
+*/
+
+Route::middleware('auth:api')->get('/admin', function (Request $request) {
+    return $request->user();
+});
+
+Route::namespace('Api')->group(function () {
+    //获取api认证token
+    Route::post('oauth/token', 'TokenController@token');
+});

+ 48 - 0
Modules/Admin/Routes/web.php

@@ -0,0 +1,48 @@
+<?php
+
+/*
+|--------------------------------------------------------------------------
+| Web Routes
+|--------------------------------------------------------------------------
+|
+| Here is where you can register web routes for your application. These
+| routes are loaded by the RouteServiceProvider within a group which
+| contains the "web" middleware group. Now create something great!
+|
+*/
+
+Route::prefix('admin')->group(function() {
+    //后台首页
+    Route::get('/', 'AdminController@index')->middleware('auth');
+    //后台登录
+    Route::get('/login', 'LoginController@loginView');
+    Route::post('/login', 'LoginController@doLogin');
+    //退出登录
+    Route::get('/logout', 'LoginController@logout');
+    //后台首页
+    Route::get('/welcome', 'AdminController@welcomeView');
+
+    //菜单管理
+    Route::get('/menus/list', 'MenusController@index');
+    Route::get('/menus/add', 'MenusController@add');
+    Route::post('/menus/add', 'MenusController@addPost');
+    Route::get('/menus/edit', 'MenusController@edit');
+    Route::post('/menus/edit', 'MenusController@editPost');
+    Route::post('/menus/del', 'MenusController@delPost');
+
+    //用户管理
+    Route::get('/users', 'UsersController@index');
+    Route::get('/users/list', 'UsersController@userList');
+    Route::get('/users/list/view', 'UsersController@userDetail');
+    Route::get('/users/list/add', 'UsersController@add');
+    Route::post('/users/list/add', 'UsersController@addPost');
+    Route::get('/users/list/edit', 'UsersController@edit');
+    Route::post('/users/list/edit', 'UsersController@editPost');
+    Route::post('/users/list/del', 'UsersController@delPost');
+    Route::get('/users/list/resetpassword', 'UsersController@resetPassword');
+//    Route::get('/users/roles/change', 'UsersController@rolesChange');
+    Route::match(['get', 'post'], '/users/roles/edit', 'UsersController@roles');
+});
+
+//菜单导出文件
+Route::get('/file/menu', 'MenusController@makeMenuToFile');

+ 57 - 0
Modules/Admin/Services/FilterService.php

@@ -0,0 +1,57 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: qiuzijian
+ * Date: 2021-04-14
+ * Time: 17:06
+ */
+
+namespace Modules\Admin\Services;
+
+class FilterService
+{
+    //检测访问的ip是否为规定的允许的ip
+    public static function check_ip()
+    {
+        if (!env('FILTER_IP')) {
+            return;
+        }
+        $ip_address = env('FILTER_IP');
+        $ALLOWED_IP = explode(',', $ip_address);
+
+        $IP           = self::getIP();
+        $check_ip_arr = explode('.', $IP);//要检测的ip拆分成数组
+        #限制IP
+        if (!in_array($IP, $ALLOWED_IP)) {
+            foreach ($ALLOWED_IP as $val) {
+                if (strpos($val, '*') !== false) {//发现有*号替代符
+                    $arr = [];//
+                    $arr = explode('.', $val);
+                    $bl  = true;//用于记录循环检测中是否有匹配成功的
+                    for ($i = 0; $i < 4; $i++) {
+                        if ($arr[$i] != '*') {//不等于*  就要进来检测,如果为*符号替代符就不检查
+                            if ($arr[$i] != $check_ip_arr[$i]) {
+                                $bl = false;
+                                break;//终止检查本个ip 继续检查下一个ip
+                            }
+                        }
+                    }//end for
+                    if ($bl) {//如果是true则找到有一个匹配成功的就返回
+                        return;
+                        die;
+                    }
+                }
+            }//end foreach
+            // header('HTTP/1.1 403 Forbidden');
+            echo "应网络安全策略,网站与App服务后台暂时关闭。";
+            die;
+        }
+    }
+
+    //获得访问的IP
+    public static function getIP() {
+        return isset($_SERVER["HTTP_X_FORWARDED_FOR"])?$_SERVER["HTTP_X_FORWARDED_FOR"]
+            :(isset($_SERVER["HTTP_CLIENT_IP"])?$_SERVER["HTTP_CLIENT_IP"]
+                :$_SERVER["REMOTE_ADDR"]);
+    }
+}

+ 255 - 0
Modules/Admin/Services/MenusService.php

@@ -0,0 +1,255 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: qiuzijian
+ * Date: 2021-04-15
+ * Time: 11:08
+ */
+
+namespace Modules\Admin\Services;
+
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Log;
+use Modules\Admin\Entities\Menu;
+
+class MenusService{
+    /**
+     * 添加菜单
+     * @param        $menuInfo
+     * @param string $key
+     * @return string
+     */
+    public function addMenu($menuInfo, $key = 'id')
+    {
+        return $this->addOrEditMenu($menuInfo, $key);
+    }
+
+    /**
+     * 获取菜单列表
+     * @param string $show
+     * @param string $category
+     * @return array|mixed|string
+     */
+    public function getMenusList($show = '', $category = 'admin')
+    {
+        // 判断并获取缓存
+        if (empty($show)) {
+            if (Cache::has($category . 'MenusList')) {
+                return Cache::get($category . 'MenusList');
+            }
+        } else {
+            if (Cache::has($category . 'MenusShowList')) {
+                return Cache::get($category . 'MenusShowList');
+            }
+        }
+
+        return $this->sortMenuAndCache($show, $category);
+    }
+
+    /**
+     * 排序子菜单并缓存
+     * ---------------------------------
+     * array_column($array,$name)
+     * $array => 要查询的数组
+     * $name  => 在数组中要返回的字段值
+     *----------------------------------
+     * array_multisort($array1,$rule,$array2)
+     * $array1 => 规定数组(规定以这个数组来排序)
+     * $rule   => 规定排列顺序。
+     * 可能的值:
+     *   SORT_ASC - 默认。按升序排列 (A-Z)。
+     *   SORT_DESC - 按降序排列 (Z-A)。
+     * $array2 => 要规定的数组。(要排序的数组)
+     */
+    public function sortMenuAndCache($show = '', $category = 'admin')
+    {
+        $menus = Menu::where('category', $category);
+        if (!empty($show)) {
+            $menus = $menus->where('show', $show);
+        }
+        $menus = $menus->orderBy('sort', 'desc')->get()->toArray();
+        if ($menus) {
+            $menuList = $this->sortMenu($menus);
+            foreach ($menuList as $key => $value) {
+                if ($value['child']) {
+                    $sort = array_column($value['child'], 'sort');
+                    array_multisort($sort, SORT_DESC, $value['child']);
+                }
+            }
+
+            //缓存菜单数据
+            if (!empty($show)) {
+                Cache::forever($category . 'MenusShowList', $menuList);
+            } else {
+                Cache::forever($category . 'MenusList', $menuList);
+            }
+            return $menuList;
+        }
+        return [];
+    }
+
+    /**
+     * 递归菜单数据
+     * @param     $menus
+     * @param int $pid
+     * @return array|string
+     */
+    public function sortMenu($menus, $pid = 0)
+    {
+        $arr = [];
+        if (empty($menus)) {
+            return '';
+        }
+        $num = 0;
+        foreach ($menus as $key => $value) {
+            if ($value['parent_id'] == $pid) {
+                $arr[$num]          = $value;
+                $arr[$num]['child'] = self::sortMenu($menus, $value['id']);
+                $num                += 1;
+            }
+        }
+        return $arr;
+    }
+
+    /**
+     * 递归删除菜单
+     * @param $menuId
+     * @return bool
+     */
+    public function delMenu($menuId, $category = 'admin')
+    {
+        $menu     = Menu::find($menuId);
+        $subMenus = Menu::where('parent_id', $menuId)->get()->toArray();
+        if (count($subMenus) > 0) {  // 如果有子菜单将子菜单删除
+            foreach ($subMenus as $subMenu) {
+                self::delMenu($subMenu['id']);
+            }
+        }
+//        $permission = Permission::where('name', $menu['slug'])
+//                                ->where('route', $menu['path'])
+//                                ->where('guard_name', 'admin')->first();
+//
+//        if ($permission) {
+//            $permission->delete();
+//        }
+        if ($menu) {
+            $menu->delete();
+        }
+        $this->sortMenuAndCache(1, $category);
+        $this->sortMenuAndCache('', $category);
+        return true;
+    }
+
+    /**
+     * 获取单个菜单信息
+     * @param $menuId
+     * @return bool
+     */
+    public function getMenuInfo($menuId)
+    {
+        if (!isset($menuId)) {
+            return false;
+        }
+        return Menu::find($menuId);
+    }
+
+    /**
+     * 编辑菜单
+     * @param $menuInfo
+     * @return bool
+     */
+    public function editMenu($menuInfo)
+    {
+        if (!isset($menuInfo['id'])) {
+            return false;
+        }
+        if ($menuInfo['id'] == $menuInfo['parent_id']) {
+            return false;
+        }
+        return $this->addOrEditMenu($menuInfo);
+    }
+
+    protected function addOrEditMenu($menuInfo, $key = 'id')
+    {
+        // 判断层级
+        if ($menuInfo['parent_id'] == 0) {
+            $menuInfo['tier'] = 1;
+            $degree           = '';
+        } else {
+            $menuParent       = Menu::find($menuInfo['parent_id']);
+            $menuInfo['tier'] = $menuParent->tier + 1;
+            $degree           = $menuParent->degree . '|';
+        }
+
+        // 判断分类
+        if (!isset($menuInfo['category'])) {
+            $menuInfo['category'] = 'admin';
+        }
+        if (!isset($menuInfo['can_del'])) {
+            $menuInfo['can_del'] = 1;
+        }
+
+        // 增加部门标识(如果为空则自动生成拼音)
+        if (!isset($menuInfo['slug']) || empty($menuInfo['slug'])) {
+            $cn = "/[\x{4e00}-\x{9fa5}a-zA-Z0-9\/]/u"; // 提取字母中文以及'/'
+            preg_match_all($cn, $menuInfo['path'], $pathResult);
+            $pathResult       = implode('', $pathResult[0]);
+            $menuInfo['slug'] = lcfirst(implode(array_map(function ($item) {
+                return ucfirst($item);
+            }, pinyin($pathResult))));
+        }
+
+        // 更新前数据
+        if (isset($menuInfo[$key]) && !empty($menuInfo[$key])) {
+            $oldMenu = Menu::where($key, $menuInfo[$key])->first();
+            if ($oldMenu) {
+                $permissionName = $oldMenu['slug'];
+            }
+        } else {
+            $menuHas = Menu::where('slug', $menuInfo['slug'])->first();
+            if ($menuHas) {
+                return 'has';
+            }
+            $permissionName = $menuInfo['slug'];
+        }
+
+        $menu         = Menu::updateOrCreate([$key => $menuInfo[$key] ?? ''], $menuInfo);
+        $menu->degree = $degree . $menu->id;
+        // 保存数据
+        $menu->save();
+
+        // 修改子树中数据,未改变层级不进行调整
+        if (isset($menuInfo[$key]) && isset($oldMenu['degree']) && $oldMenu['degree'] != $menu['degree']) {  // 如果改变父级,联动改变其下属所有子集
+
+            // 层级
+            $diffTier = $oldMenu['tier'] - $menuInfo['tier'];
+            // 查找子数据数组(array)
+            $childMenus = Menu::where('degree', 'like', $oldMenu['degree'] . '|%')->get();
+            foreach ($childMenus as $childMenu) {
+                // 第一条子数据
+                // 修改树路径:修改的树|更新的树|子树
+                $degree = str_replace($oldMenu['degree'] . '|', $menu['degree'] . '|', $childMenu['degree']);
+                // 获取详情
+                $_menu = Menu::where('id', $childMenu['id'])->first();
+                // 路劲数据
+                $_menu->degree = $degree;
+                // 层级
+                $_menu->tier = $_menu->tier - $diffTier;
+                // 保存
+                $_menu->save();
+            }
+        }
+
+        // 权限
+        $permissionInfo['title']      = $menuInfo['title'];
+        $permissionInfo['name']       = $menuInfo['slug'];
+        $permissionInfo['route']      = $menuInfo['path'];
+        $permissionInfo['guard_name'] = $menuInfo['category'];
+//        Permission::updateOrCreate(['name' => $permissionName ?? ''], $permissionInfo);
+
+        $this->sortMenuAndCache(1, $menuInfo['category']);
+        $this->sortMenuAndCache('', $menuInfo['category']);
+
+        return $menu;
+    }
+}

+ 135 - 0
Modules/Admin/Services/UsersService.php

@@ -0,0 +1,135 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: qiuzijian
+ * Date: 2021-04-16
+ * Time: 10:52
+ */
+
+namespace Modules\Admin\Services;
+
+use App\User;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Log;
+use Modules\Admin\Enum\AdminEnum;
+use Modules\Admin\Enum\UserEnum;
+
+class UsersService{
+
+    //添加用户
+    public static function addAdminUser($params)
+    {
+        $result['status'] = true;
+        $result['msg']    = AdminEnum::RETURN_SUCCESS;
+
+        //判断该用户编码是否已存在
+        $query = User::where('staff_num', $params['staff_num'])->first();
+        if ($query) {
+            $result['status'] = false;
+            $result['msg']    = AdminEnum::USER_ALREADY_EXIST;
+            return $result;
+        }
+
+        //入库动作
+        $res = User::insert(
+            [
+                'name'       => $params['name'],
+                'mobile'     => $params['mobile'],
+                'staff_num'  => $params['staff_num'],
+                'password'   => bcrypt(UserEnum::ADMIN_USER_DETAULT_PASSWORD),
+                'created_at' => date('Y-m-d H:i:s'),
+                'updated_at' => date('Y-m-d H:i:s'),
+            ]
+        );
+
+        if (!$res) {
+            $result['status'] = false;
+            $result['msg']    = AdminEnum::DATABASE_ERROR;
+        }
+
+        return $result;
+    }
+
+    //编辑用户
+    public static function editAdminUser($params)
+    {
+        $result['status'] = true;
+        $result['msg']    = AdminEnum::RETURN_SUCCESS;
+
+        $query = User::where('staff_num', $params['staff_num'])->first();
+
+        if (!$query) {
+            $result['status'] = true;
+            $result['msg']    = AdminEnum::USER_NOT_EXIST;
+            return $result;
+        }
+
+        $res = User::where('id', $query->id)->update(
+            [
+                'name'       => $params['name'],
+                'mobile'     => $params['mobile'],
+                'staff_num'  => $params['staff_num'],
+                'updated_at' => date('Y-m-d H:i:s'),
+            ]
+        );
+
+        if (!$res) {
+            $result['status'] = false;
+            $result['msg']    = AdminEnum::DATABASE_ERROR;
+        }
+
+        return $result;
+    }
+
+    //删除用户
+    public static function delAdminUser($params)
+    {
+        $result['status'] = true;
+        $result['msg']    = AdminEnum::RETURN_SUCCESS;
+
+        $query = User::where('staff_num', $params['staff_num'])->first();
+
+        if (!$query) {
+            $result['status'] = true;
+            $result['msg']    = AdminEnum::USER_NOT_EXIST;
+            return $result;
+        }
+
+        $res = User::where('id', $query->id)->delete();
+
+        if (!$res) {
+            $result['status'] = false;
+            $result['msg']    = AdminEnum::DATABASE_ERROR;
+        }
+
+        return $result;
+    }
+
+    //重置用户密码
+    public static function resetPassword($params)
+    {
+        $result['status'] = true;
+        $result['msg']    = AdminEnum::RETURN_SUCCESS;
+
+        $query = User::where('staff_num', $params['staff_num'])->first();
+
+        if (!$query) {
+            $result['status'] = true;
+            $result['msg']    = AdminEnum::USER_NOT_EXIST;
+            return $result;
+        }
+
+        $res = User::where('id', $query->id)->update(
+            [
+                'password' => bcrypt(UserEnum::ADMIN_USER_DETAULT_PASSWORD),
+            ]
+        );
+
+        if (!$res) {
+            $result['status'] = false;
+            $result['msg']    = AdminEnum::DATABASE_ERROR;
+        }
+
+        return $result;
+    }
+}

+ 0 - 0
Modules/Admin/Tests/Feature/.gitkeep


+ 0 - 0
Modules/Admin/Tests/Unit/.gitkeep


+ 259 - 0
Modules/Admin/Traits/ClassifyMethod.php

@@ -0,0 +1,259 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: qiuzijian
+ * Date: 2021-04-17
+ * Time: 17:16
+ */
+
+namespace Modules\Admin\Traits;
+
+use Illuminate\Support\Arr;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Log;
+
+trait ClassifyMethod
+{
+    /**
+     * 模型对象
+     * @var
+     */
+    protected $classify;
+
+    /**
+     * 缓存名
+     * @var string
+     */
+    public $cacheTitle = 'Classify';
+
+    /**
+     * 排序方式
+     * @var string
+     */
+    public $sort = 'desc';
+
+    /**
+     * 删除
+     * @param $classifyInfo
+     * @return mixed
+     */
+    public function add($classifyInfo)
+    {
+        return $this->addOrEdit($classifyInfo);
+    }
+
+    /**
+     * 添加
+     * @param $classifyInfo
+     * @return bool
+     */
+    public function edit($classifyInfo)
+    {
+        if (!isset($classifyInfo['id'])) {
+            return false;
+        }
+        return $this->addOrEdit($classifyInfo);
+    }
+
+    /**
+     * 递归删除
+     * @param $classifyId
+     * @return bool
+     */
+    public function del($classifyId)
+    {
+        if (empty($classifyId)) {
+            return false;
+        }
+        $classify = $this->classify->find($classifyId);
+//        $subClassifys = $this->classify->where('parent_id', $classifyId)->get()->toArray();
+//        if (count($subClassifys) > 0) {  // 如果有子菜单将子菜单删除
+//            foreach ($subClassifys as $subClassify) {
+//                self::del($subClassify['id']);
+//            }
+//        }
+        if ($classify) {
+            $this->classify->where('degree', 'like', $classify->degree . '|%')->delete();
+            $classify->delete();
+        }
+        $this->sortClassifyAndddCache(1);
+        $this->sortClassifyAndddCache();
+        return true;
+    }
+
+    /**
+     * 获取单个信息
+     * @param $classifyId
+     * @return false
+     */
+    public function getOneInfo($classifyId)
+    {
+        if (!$classifyId) {
+            return false;
+        }
+        return $this->classify->find($classifyId);
+    }
+
+    /**
+     * 获取所有
+     * @return mixed
+     */
+    public function getAll($show = '')
+    {
+        if (!empty($show)) {
+            return $this->classify->where('show', $show)->all();
+        }
+        return $this->classify->all();
+    }
+
+    /**
+     * 获取层级列表
+     * @param string $show
+     * @param string $category
+     * @return array|mixed|string
+     */
+    public function getTierList($show = '', $degree = '')
+    {
+        // 判断并获取缓存
+        if (!empty($show)) {
+            if (Cache::has($this->cacheTitle . 'ShowList')) {
+                $classifyList = Cache::get($this->cacheTitle . 'ShowList');
+            } else {
+                $classifyList = $this->sortClassifyAndddCache(1);
+            }
+        } else {
+            if (Cache::has($this->cacheTitle . 'List')) {
+                $classifyList = Cache::get($this->cacheTitle . 'List');
+            } else {
+                $classifyList = $this->sortClassifyAndddCache();
+            }
+        }
+
+        $classifyList = empty($classifyList) ? [] : $classifyList;
+        if (empty($degree)) {
+            return $classifyList;
+        }
+
+        return Arr::get($classifyList, $degree);
+
+    }
+
+
+    /**
+     * 递归岗位数据
+     * @param     $classify
+     * @param int $pid
+     * @return array|string
+     */
+    public function sortClassify($classify, $pid = '0')
+    {
+        $arr = [];
+        if (empty($classify)) {
+            return '';
+        }
+        $num = 0;
+        foreach ($classify as $key => $value) {
+            if ($value['parent_id'] == $pid) {
+                $arr[$num]          = $value;
+                $arr[$num]['child'] = self::sortClassify($classify, $value['id']);
+                if (count($arr[$num]['child']) == 0) {
+                    unset($arr[$num]['child']);
+                }
+                $num++;
+            }
+        }
+        return $arr;
+    }
+
+    /**
+     * 排序子岗位并缓存
+     * ---------------------------------
+     * array_column($array,$name)
+     * $array => 要查询的数组
+     * $name  => 在数组中要返回的字段值
+     *----------------------------------
+     * array_multisort($array1,$rule,$array2)
+     * $array1 => 规定数组(规定以这个数组来排序)
+     * $rule   => 规定排列顺序。
+     * 可能的值:
+     *   SORT_ASC - 默认。按升序排列 (A-Z)。
+     *   SORT_DESC - 按降序排列 (Z-A)。
+     * $array2 => 要规定的数组。(要排序的数组)
+     */
+    public function sortClassifyAndddCache($show = '')
+    {
+        $classify = $this->classify;
+        if (!empty($show)) {
+            $classify = $classify->where('show', $show);
+        }
+        $classify = $classify->orderBy('sort', $this->sort)->get()->toArray();
+        if ($classify) {
+            $classifyList = $this->sortClassify($classify);
+            foreach ($classifyList as $key => $value) {
+                if (isset($value['child'])) {
+                    $sort = array_column($value['child'], 'sort');
+                    if ($this->sort == 'desc') {
+                        array_multisort($sort, SORT_ASC, $value['child']);
+                    } else {
+                        array_multisort($sort, SORT_DESC, $value['child']);
+                    }
+                }
+            }
+            if (!empty($show)) {
+                Cache::forever($this->cacheTitle . 'ShowList', $classifyList);
+            } else {
+                Cache::forever($this->cacheTitle . 'List', $classifyList);
+            }
+            return $classifyList;
+        }
+        Cache::forget($this->cacheTitle . 'List');
+        Cache::forget($this->cacheTitle . 'ShowList');
+        return '';
+    }
+
+    protected function addOrEdit($classifyInfo)
+    {
+        // 判断层级
+        $classifyInfo['parent_id'] = $classifyInfo['parent_id'] ?? 0;
+        if ($classifyInfo['parent_id'] == 0) {
+            $classifyInfo['tier'] = 1;
+            $degree               = '';
+        } else {
+            $classifyParent       = $this->classify->find($classifyInfo['parent_id']);
+            $classifyInfo['tier'] = $classifyParent->tier + 1;
+            $degree               = $classifyParent->degree . '|';
+        }
+        // 将标题转化成拼音作为标记
+        if (empty($classifyInfo['slug'])) {
+            $classifyInfo['slug'] = implode(array_map(function ($v) {
+                return ucfirst($v);
+            }, pinyin($classifyInfo['title'])));
+        }
+
+        if (isset($classifyInfo['id'])) {
+            $curClassifyInfo = $this->classify->find($classifyInfo['id']);
+        }
+
+        $classify         = $this->classify->updateOrCreate(['id' => $classifyInfo['id'] ?? ''], $classifyInfo);
+        $classify->degree = $degree . $classify->id;
+        $classify->save();
+
+        // 更新子集
+        if (isset($classifyInfo['id']) && $curClassifyInfo['degree'] != $classify['degree']) {  // 如果改变父级,联动改变其下属所有子集
+            $diffTier       = $curClassifyInfo['tier'] - $classifyInfo['tier'];
+            $childClassifys = $this->classify->where('degree', 'like', $curClassifyInfo['degree'] . '|%')->get();
+            foreach ($childClassifys as $childClassify) {
+                $degree            = str_replace($curClassifyInfo['degree'] . '|', $classify['degree'] . '|', $childClassify['degree']);
+                $_classify         = $this->classify->where('id', $childClassify['id'])->first();
+                $_classify->degree = $degree;
+                $_classify->tier   = $_classify->tier - $diffTier;
+                $_classify->save();
+            }
+        }
+
+        $this->sortClassifyAndddCache(1);
+        $this->sortClassifyAndddCache();
+
+        return $classify;
+    }
+}

+ 23 - 0
Modules/Admin/composer.json

@@ -0,0 +1,23 @@
+{
+    "name": "nwidart/admin",
+    "description": "",
+    "authors": [
+        {
+            "name": "Nicolas Widart",
+            "email": "n.widart@gmail.com"
+        }
+    ],
+    "extra": {
+        "laravel": {
+            "providers": [],
+            "aliases": {
+
+            }
+        }
+    },
+    "autoload": {
+        "psr-4": {
+            "Modules\\Admin\\": ""
+        }
+    }
+}

+ 13 - 0
Modules/Admin/module.json

@@ -0,0 +1,13 @@
+{
+    "name": "Admin",
+    "alias": "admin",
+    "description": "",
+    "keywords": [],
+    "order": 0,
+    "providers": [
+        "Modules\\Admin\\Providers\\AdminServiceProvider"
+    ],
+    "aliases": {},
+    "files": [],
+    "requires": []
+}

+ 17 - 0
Modules/Admin/package.json

@@ -0,0 +1,17 @@
+{
+    "private": true,
+    "scripts": {
+        "dev": "npm run development",
+        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
+        "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
+        "watch-poll": "npm run watch -- --watch-poll",
+        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
+        "prod": "npm run production",
+        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
+    },
+    "devDependencies": {
+        "cross-env": "^7.0",
+        "laravel-mix": "^5.0.1",
+        "laravel-mix-merge-manifest": "^0.1.2"
+    }
+}

+ 14 - 0
Modules/Admin/webpack.mix.js

@@ -0,0 +1,14 @@
+const dotenvExpand = require('dotenv-expand');
+dotenvExpand(require('dotenv').config({ path: '../../.env'/*, debug: true*/}));
+
+const mix = require('laravel-mix');
+require('laravel-mix-merge-manifest');
+
+mix.setPublicPath('../../public').mergeManifest();
+
+mix.js(__dirname + '/Resources/assets/js/app.js', 'js/admin.js')
+    .sass( __dirname + '/Resources/assets/sass/app.scss', 'css/admin.css');
+
+if (mix.inProduction()) {
+    mix.version();
+}

+ 0 - 0
Modules/Camera/Config/.gitkeep


+ 5 - 0
Modules/Camera/Config/config.php

@@ -0,0 +1,5 @@
+<?php
+
+return [
+    'name' => 'Camera'
+];

+ 0 - 0
Modules/Camera/Console/.gitkeep


+ 0 - 0
Modules/Camera/Database/Migrations/.gitkeep


+ 33 - 0
Modules/Camera/Database/Migrations/2021_04_20_071702_create_camera_field_list.php

@@ -0,0 +1,33 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class CreateCameraFieldList extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('camera_field_list', function (Blueprint $table) {
+            $table->bigIncrements('id')->comment('摄像头链接生成字段列表');
+            $table->string('field_name', 20)->comment('字段名称');
+            $table->timestamps();
+            $table->softDeletes();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('camera_field_list');
+    }
+}

+ 40 - 0
Modules/Camera/Database/Migrations/2021_04_20_082221_create_camera_list_table.php

@@ -0,0 +1,40 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class CreateCameraListTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('camera_list', function (Blueprint $table) {
+            $table->bigIncrements('id')->comment('摄像头管理表');
+            $table->integer('mine_id')->index()->comment('矿区id(mine_list表id)');
+            $table->string('ip', 50)->nullable()->comment('ip地址');
+            $table->string('port', 10)->nullable()->comment('端口');
+            $table->string('user_name', 50)->nullable()->comment('用户名');
+            $table->string('password', 100)->nullable()->comment('密码');
+            $table->string('com_number', 100)->nullable()->comment('通讯号');
+            $table->tinyInteger('status')->default(0)->comment('状态');
+            $table->string('camera_url')->nullable()->comment('拼接完成的请求链接');
+            $table->timestamps();
+            $table->softDeletes();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('camera_list');
+    }
+}

+ 34 - 0
Modules/Camera/Database/Migrations/2021_04_23_032650_update_camera_list_table_fields.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class UpdateCameraListTableFields extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->string('camera_name', 100)->after('camera_url')->comment('摄像头名称');
+            $table->string('revert_id', 20)->after('camera_url')->comment('流媒体返回id');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->dropColumn('camera_name');
+            $table->dropColumn('revert_id');
+        });
+    }
+}

+ 32 - 0
Modules/Camera/Database/Migrations/2021_04_26_024115_add_sort_to_camera_list_table.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class AddSortToCameraListTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->integer('sort')->default(1)->after('revert_id')->comment('排序');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->dropColumn('sort');
+        });
+    }
+}

+ 32 - 0
Modules/Camera/Database/Migrations/2021_05_11_092132_add_camera_type_to_camera_list.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class AddCameraTypeToCameraList extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->tinyInteger('camera_type')->after('camera_name')->default(1)->index()->comment('摄像头类型');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->dropColumn('camera_type');
+        });
+    }
+}

+ 34 - 0
Modules/Camera/Database/Migrations/2021_05_19_070340_add_field_to_camera_list_05191503.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class AddFieldToCameraList05191503 extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->string('index_code')->nullable()->after('camera_type')->comment('海康摄像头index_code');
+            $table->tinyInteger('camera_source')->default(1)->after('camera_type')->comment('摄像头来源 1:视频录像机 2: 视频服务器');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->dropColumn('index_code');
+            $table->dropColumn('camera_source');
+        });
+    }
+}

+ 32 - 0
Modules/Camera/Database/Migrations/2021_08_02_074532_add_is_show_to_camera_list.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class AddIsShowToCameraList extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->tinyInteger('is_show')->after('index_code')->default('1')->index()->comment('是否显示 1:是 2:否');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->dropColumn('is_show');
+        });
+    }
+}

+ 32 - 0
Modules/Camera/Database/Migrations/2021_08_05_095128_add_code_stream_to_camera_list.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class AddCodeStreamToCameraList extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->tinyInteger('code_stream')->after('is_show')->default('1')->comment('视频码流 1:子码流 2:主码流');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->dropColumn('code_stream');
+        });
+    }
+}

+ 32 - 0
Modules/Camera/Database/Migrations/2021_08_10_102022_add_cover_picture_to_camera_list.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class AddCoverPictureToCameraList extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->text('cover_picture')->after('code_stream')->nullable()->comment('封面图片');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->dropColumn('cover_picture');
+        });
+    }
+}

+ 32 - 0
Modules/Camera/Database/Migrations/2021_12_22_162404_add_field_to_camera_list.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class AddFieldToCameraList extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->tinyInteger('video_recorder')->after('cover_picture')->default('1')->comment('视频服务器来源 1:海康 2:大华(camera_source为1是使用)');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->dropColumn('video_recorder');
+        });
+    }
+}

+ 32 - 0
Modules/Camera/Database/Migrations/2022_01_21_151316_add_field_to_camera_list_2021_01_21.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class AddFieldToCameraList20210121 extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->tinyInteger('camera_status')->after('video_recorder')->default('1')->comment('摄像头状态 1:在线 2:离线');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->dropColumn('camera_status');
+        });
+    }
+}

+ 40 - 0
Modules/Camera/Database/Migrations/2022_07_08_153542_create_playback.php

@@ -0,0 +1,40 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class CreatePlayback extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('playback', function (Blueprint $table) {
+            $table->bigIncrements('id')->comment('ID');
+            $table->integer('camera_id')->index()->comment('摄像头ID');
+            $table->string('title')->nullable()->comment('时间段标题');
+            $table->string('start_time')->nullable()->comment('开始时间');
+            $table->string('end_time')->nullable()->comment('开始时间');
+            $table->timestamps();
+            $table->softDeletes();
+        });
+
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->tinyInteger('playback')->default('0')->comment('可回放 0:不可以 1:可以');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('playback');
+    }
+}

+ 30 - 0
Modules/Camera/Database/Migrations/2022_07_19_172431_update_camera_list_table.php

@@ -0,0 +1,30 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class UpdateCameraListTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->string('revert_back_id')->default('NullId')->comment('easydrawin回放标识');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        //
+    }
+}

+ 30 - 0
Modules/Camera/Database/Migrations/2022_07_21_180042_update_play_back_table.php

@@ -0,0 +1,30 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class UpdatePlayBackTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('playback', function (Blueprint $table) {
+            $table->string('revert_back_id')->default('NullId')->comment('easydrawin回放标识');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        //
+    }
+}

+ 30 - 0
Modules/Camera/Database/Migrations/2023_02_02_123955_update_camera_base64_table.php

@@ -0,0 +1,30 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class UpdateCameraBase64Table extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('camera_list', function (Blueprint $table) {
+            $table->longText('base64',255)->nullable()->comment('base64首帧图片');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        //
+    }
+}

+ 0 - 0
Modules/Camera/Database/Seeders/.gitkeep


+ 21 - 0
Modules/Camera/Database/Seeders/CameraDatabaseSeeder.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace Modules\Camera\Database\Seeders;
+
+use Illuminate\Database\Seeder;
+use Illuminate\Database\Eloquent\Model;
+
+class CameraDatabaseSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        Model::unguard();
+
+        // $this->call("OthersTableSeeder");
+    }
+}

+ 0 - 0
Modules/Camera/Database/factories/.gitkeep


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