Browse Source

0720-0127-h01

Zory 2 tuần trước cách đây
commit
dcdfcf7578
100 tập tin đã thay đổi với 11484 bổ sung0 xóa
  1. 9 0
      .env
  2. 8 0
      .idea/.gitignore
  3. 8 0
      .idea/modules.xml
  4. 131 0
      .idea/php.xml
  5. 10 0
      .idea/phpspec.xml
  6. 112 0
      .idea/poem-api.iml
  7. 6 0
      .idea/vcs.xml
  8. 18 0
      Dockerfile
  9. 21 0
      LICENSE
  10. 70 0
      README.md
  11. 131 0
      app/command/Model.php
  12. 116 0
      app/command/PoemAuthor.php
  13. 99 0
      app/command/PoemData.php
  14. 50 0
      app/command/ShopwwiAuthCommand.php
  15. 91 0
      app/controller/IndexController.php
  16. 29 0
      app/extra/basic/Model.php
  17. 74 0
      app/functions.php
  18. 42 0
      app/middleware/StaticFile.php
  19. 50 0
      app/model/dynasty/Dynasty.php
  20. 50 0
      app/model/dynasty/DynastyAuthor.php
  21. 42 0
      app/model/dynasty/DynastyAuthorInfo.php
  22. 47 0
      app/model/dynasty/DynastyCategory.php
  23. 48 0
      app/model/poem/PoemData.php
  24. 10 0
      app/process/Http.php
  25. 305 0
      app/process/Monitor.php
  26. 14 0
      app/view/index/view.html
  27. 82 0
      composer.json
  28. 5350 0
      composer.lock
  29. 26 0
      config/app.php
  30. 21 0
      config/autoload.php
  31. 18 0
      config/bootstrap.php
  32. 7 0
      config/container.php
  33. 15 0
      config/dependence.php
  34. 5 0
      config/event.php
  35. 17 0
      config/exception.php
  36. 32 0
      config/log.php
  37. 15 0
      config/middleware.php
  38. 48 0
      config/plugin/linfly/annotation/annotation.php
  39. 4 0
      config/plugin/linfly/annotation/app.php
  40. 19 0
      config/plugin/linfly/annotation/bootstrap.php
  41. 19 0
      config/plugin/linfly/annotation/middleware.php
  42. 17 0
      config/plugin/linfly/annotation/route.php
  43. 71 0
      config/plugin/shopwwi/auth/app.php
  44. 76 0
      config/plugin/tinywan/storage/app.php
  45. 28 0
      config/plugin/webman/console/app.php
  46. 4 0
      config/plugin/webman/event/app.php
  47. 17 0
      config/plugin/webman/event/bootstrap.php
  48. 7 0
      config/plugin/webman/event/command.php
  49. 4 0
      config/plugin/webman/redis-queue/app.php
  50. 7 0
      config/plugin/webman/redis-queue/command.php
  51. 32 0
      config/plugin/webman/redis-queue/log.php
  52. 11 0
      config/plugin/webman/redis-queue/process.php
  53. 21 0
      config/plugin/webman/redis-queue/redis.php
  54. 8 0
      config/plugin/webman/validation/app.php
  55. 7 0
      config/plugin/webman/validation/command.php
  56. 9 0
      config/plugin/webman/validation/middleware.php
  57. 50 0
      config/process.php
  58. 29 0
      config/redis.php
  59. 21 0
      config/route.php
  60. 23 0
      config/server.php
  61. 65 0
      config/session.php
  62. 23 0
      config/static.php
  63. 44 0
      config/think-cache.php
  64. 42 0
      config/think-orm.php
  65. 25 0
      config/translation.php
  66. 22 0
      config/view.php
  67. 11 0
      docker-compose.yml
  68. BIN
      public/favicon.ico
  69. 4 0
      runtime/.gitignore
  70. 2 0
      runtime/logs/.gitignore
  71. 2 0
      runtime/views/.gitignore
  72. 5 0
      start.php
  73. 24 0
      support/Request.php
  74. 24 0
      support/Response.php
  75. 1558 0
      support/Setup.php
  76. 3 0
      support/bootstrap.php
  77. 2 0
      vendor/aliyuncs/oss-sdk-php/.coveralls.yml
  78. 45 0
      vendor/aliyuncs/oss-sdk-php/.github/workflows/main.yml
  79. 35 0
      vendor/aliyuncs/oss-sdk-php/.github/workflows/release.yml
  80. 8 0
      vendor/aliyuncs/oss-sdk-php/.gitignore
  81. 21 0
      vendor/aliyuncs/oss-sdk-php/.travis.yml
  82. 163 0
      vendor/aliyuncs/oss-sdk-php/CHANGELOG.md
  83. 21 0
      vendor/aliyuncs/oss-sdk-php/LICENSE.md
  84. 154 0
      vendor/aliyuncs/oss-sdk-php/README-CN.md
  85. 155 0
      vendor/aliyuncs/oss-sdk-php/README.md
  86. 11 0
      vendor/aliyuncs/oss-sdk-php/autoload.php
  87. 13 0
      vendor/aliyuncs/oss-sdk-php/build-phar.sh
  88. 24 0
      vendor/aliyuncs/oss-sdk-php/composer.json
  89. BIN
      vendor/aliyuncs/oss-sdk-php/example.jpg
  90. 3 0
      vendor/aliyuncs/oss-sdk-php/index.php
  91. 106 0
      vendor/aliyuncs/oss-sdk-php/phpunit.xml
  92. 254 0
      vendor/aliyuncs/oss-sdk-php/samples/Bucket.php
  93. 91 0
      vendor/aliyuncs/oss-sdk-php/samples/BucketCname.php
  94. 171 0
      vendor/aliyuncs/oss-sdk-php/samples/BucketCors.php
  95. 98 0
      vendor/aliyuncs/oss-sdk-php/samples/BucketEncryption.php
  96. 109 0
      vendor/aliyuncs/oss-sdk-php/samples/BucketLifecycle.php
  97. 95 0
      vendor/aliyuncs/oss-sdk-php/samples/BucketLogging.php
  98. 116 0
      vendor/aliyuncs/oss-sdk-php/samples/BucketPayment.php
  99. 123 0
      vendor/aliyuncs/oss-sdk-php/samples/BucketPolicy.php
  100. 101 0
      vendor/aliyuncs/oss-sdk-php/samples/BucketReferer.php

+ 9 - 0
.env

@@ -0,0 +1,9 @@
+APP_KEY = '37dbd69c19c7addf439941b41e379563'
+APP_DEBUG = false
+
+DB_HOST = mysql-1e20bdcd11c0-public.rds.volces.com
+DB_PORT = 3306
+DB_NAME = poem_new
+DB_USER = lanwei_root
+DB_PASSWORD = bluevchat@888
+DB_DEFAULT = mysql

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 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/poem-api.iml" filepath="$PROJECT_DIR$/.idea/poem-api.iml" />
+    </modules>
+  </component>
+</project>

+ 131 - 0
.idea/php.xml

@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="MessDetectorOptionsConfiguration">
+    <option name="transferred" value="true" />
+  </component>
+  <component name="PHPCSFixerOptionsConfiguration">
+    <option name="transferred" value="true" />
+  </component>
+  <component name="PHPCodeSnifferOptionsConfiguration">
+    <option name="highlightLevel" value="WARNING" />
+    <option name="transferred" value="true" />
+  </component>
+  <component name="PhpIncludePathManager">
+    <include_path>
+      <path value="$PROJECT_DIR$/vendor/brick/math" />
+      <path value="$PROJECT_DIR$/vendor/carbonphp/carbon-doctrine-types" />
+      <path value="$PROJECT_DIR$/vendor/composer" />
+      <path value="$PROJECT_DIR$/vendor/monolog/monolog" />
+      <path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
+      <path value="$PROJECT_DIR$/vendor/psr/simple-cache" />
+      <path value="$PROJECT_DIR$/vendor/symfony/clock" />
+      <path value="$PROJECT_DIR$/vendor/psr/clock" />
+      <path value="$PROJECT_DIR$/vendor/symfony/finder" />
+      <path value="$PROJECT_DIR$/vendor/psr/log" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-php84" />
+      <path value="$PROJECT_DIR$/vendor/workerman/workerman" />
+      <path value="$PROJECT_DIR$/vendor/psr/container" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-php83" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
+      <path value="$PROJECT_DIR$/vendor/workerman/webman-framework" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-php85" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
+      <path value="$PROJECT_DIR$/vendor/workerman/coroutine" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
+      <path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
+      <path value="$PROJECT_DIR$/vendor/symfony/string" />
+      <path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
+      <path value="$PROJECT_DIR$/vendor/nikic/fast-route" />
+      <path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
+      <path value="$PROJECT_DIR$/vendor/symfony/mime" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-ctype" />
+      <path value="$PROJECT_DIR$/vendor/symfony/translation" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
+      <path value="$PROJECT_DIR$/vendor/symfony/console" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
+      <path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
+      <path value="$PROJECT_DIR$/vendor/voku/portable-ascii" />
+      <path value="$PROJECT_DIR$/vendor/nesbot/carbon" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/bus" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/macroable" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/support" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/redis" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/validation" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/conditionable" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/reflection" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/collections" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/container" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/events" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/filesystem" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/contracts" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/translation" />
+      <path value="$PROJECT_DIR$/vendor/illuminate/pipeline" />
+      <path value="$PROJECT_DIR$/vendor/topthink/think-validate" />
+      <path value="$PROJECT_DIR$/vendor/topthink/think-helper" />
+      <path value="$PROJECT_DIR$/vendor/topthink/think-container" />
+      <path value="$PROJECT_DIR$/vendor/topthink/think-orm" />
+      <path value="$PROJECT_DIR$/vendor/webman/redis" />
+      <path value="$PROJECT_DIR$/vendor/webman/console" />
+      <path value="$PROJECT_DIR$/vendor/webman/validation" />
+      <path value="$PROJECT_DIR$/vendor/webman/think-orm" />
+      <path value="$PROJECT_DIR$/vendor/psr/http-client" />
+      <path value="$PROJECT_DIR$/vendor/psr/http-message" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/promises" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle" />
+      <path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
+      <path value="$PROJECT_DIR$/vendor/psr/http-factory" />
+      <path value="$PROJECT_DIR$/vendor/firebase/php-jwt" />
+      <path value="$PROJECT_DIR$/vendor/shopwwi/webman-auth" />
+      <path value="$PROJECT_DIR$/vendor/tinywan/storage" />
+      <path value="$PROJECT_DIR$/vendor/aliyuncs/oss-sdk-php" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/uri-template" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle-services" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/command" />
+      <path value="$PROJECT_DIR$/vendor/webman/think-cache" />
+      <path value="$PROJECT_DIR$/vendor/qcloud/cos-sdk-v5" />
+      <path value="$PROJECT_DIR$/vendor/workerman/redis-queue" />
+      <path value="$PROJECT_DIR$/vendor/workerman/redis" />
+      <path value="$PROJECT_DIR$/vendor/webman/redis-queue" />
+      <path value="$PROJECT_DIR$/vendor/webman/event" />
+      <path value="$PROJECT_DIR$/vendor/yzh52521/easyhttp" />
+      <path value="$PROJECT_DIR$/vendor/php-di/invoker" />
+      <path value="$PROJECT_DIR$/vendor/php-di/php-di" />
+      <path value="$PROJECT_DIR$/vendor/linfly/annotation" />
+      <path value="$PROJECT_DIR$/vendor/laravel/serializable-closure" />
+      <path value="$PROJECT_DIR$/vendor/graham-campbell/result-type" />
+      <path value="$PROJECT_DIR$/vendor/vlucas/phpdotenv" />
+      <path value="$PROJECT_DIR$/vendor/workerman/crontab" />
+      <path value="$PROJECT_DIR$/vendor/phpoption/phpoption" />
+      <path value="$PROJECT_DIR$/vendor/maennchen/zipstream-php" />
+      <path value="$PROJECT_DIR$/vendor/markbaker/complex" />
+      <path value="$PROJECT_DIR$/vendor/markbaker/matrix" />
+      <path value="$PROJECT_DIR$/vendor/phpoffice/phpspreadsheet" />
+      <path value="$PROJECT_DIR$/vendor/jaeger/querylist" />
+      <path value="$PROJECT_DIR$/vendor/jaeger/g-http" />
+      <path value="$PROJECT_DIR$/vendor/jaeger/phpquery-single" />
+      <path value="$PROJECT_DIR$/vendor/symfony/cache" />
+      <path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
+      <path value="$PROJECT_DIR$/vendor/symfony/cache-contracts" />
+      <path value="$PROJECT_DIR$/vendor/symfony/var-exporter" />
+      <path value="$PROJECT_DIR$/vendor/psr/cache" />
+      <path value="$PROJECT_DIR$/vendor/overtrue/pinyin" />
+    </include_path>
+  </component>
+  <component name="PhpProjectSharedConfiguration" php_language_level="8.2">
+    <option name="suggestChangeDefaultLanguageLevel" value="false" />
+  </component>
+  <component name="PhpStanOptionsConfiguration">
+    <option name="transferred" value="true" />
+  </component>
+  <component name="PhpUnit">
+    <phpunit_settings>
+      <PhpUnitSettings custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" />
+    </phpunit_settings>
+  </component>
+  <component name="PsalmOptionsConfiguration">
+    <option name="transferred" value="true" />
+  </component>
+</project>

+ 10 - 0
.idea/phpspec.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="PHPSpec">
+    <suites>
+      <PhpSpecSuiteConfiguration>
+        <option name="myPath" value="$PROJECT_DIR$" />
+      </PhpSpecSuiteConfiguration>
+    </suites>
+  </component>
+</project>

+ 112 - 0
.idea/poem-api.iml

@@ -0,0 +1,112 @@
+<?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$/." isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/./app" isTestSource="false" packagePrefix="app\" />
+      <sourceFolder url="file://$MODULE_DIR$/./app/view/components" isTestSource="false" packagePrefix="app\View\Components\" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/aliyuncs/oss-sdk-php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/brick/math" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/carbonphp/carbon-doctrine-types" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/inflector" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/lexer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/egulias/email-validator" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/firebase/php-jwt" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/graham-campbell/result-type" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/command" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/guzzle" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/guzzle-services" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/promises" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/psr7" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/uri-template" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/bus" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/collections" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/conditionable" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/container" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/contracts" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/events" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/filesystem" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/macroable" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/pipeline" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/redis" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/reflection" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/support" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/translation" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/illuminate/validation" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/jaeger/g-http" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/jaeger/phpquery-single" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/jaeger/querylist" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/laravel/serializable-closure" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/linfly/annotation" />
+      <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/monolog/monolog" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/nesbot/carbon" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/nikic/fast-route" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/overtrue/pinyin" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/php-di/invoker" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/php-di/php-di" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpoffice/phpspreadsheet" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpoption/phpoption" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/cache" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/clock" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/container" />
+      <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/psr/log" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/simple-cache" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/qcloud/cos-sdk-v5" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/ralouphie/getallheaders" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/shopwwi/webman-auth" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/cache" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/cache-contracts" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/clock" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/deprecation-contracts" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/finder" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-foundation" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/mime" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-ctype" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-grapheme" />
+      <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-php80" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php83" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php84" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php85" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/string" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation-contracts" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-dumper" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-exporter" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/tinywan/storage" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/topthink/think-container" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/topthink/think-helper" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/topthink/think-orm" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/topthink/think-validate" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/vlucas/phpdotenv" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/voku/portable-ascii" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/webman/console" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/webman/event" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/webman/redis" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/webman/redis-queue" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/webman/think-cache" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/webman/think-orm" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/webman/validation" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/workerman/coroutine" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/workerman/crontab" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/workerman/redis" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/workerman/redis-queue" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/workerman/webman-framework" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/workerman/workerman" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/yzh52521/easyhttp" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 6 - 0
.idea/vcs.xml

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

+ 18 - 0
Dockerfile

@@ -0,0 +1,18 @@
+FROM php:8.3.22-cli-alpine
+
+RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
+
+RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
+  && apk update --no-cache \
+  && docker-php-source extract
+
+# install extensions
+RUN docker-php-ext-install pdo pdo_mysql -j$(nproc) pcntl
+
+# enable opcache and pcntl
+RUN docker-php-ext-enable opcache pcntl
+RUN docker-php-source delete \
+    rm -rf /var/cache/apk/*
+
+RUN mkdir -p /app
+WORKDIR /app

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 walkor<walkor@workerman.net> and contributors (see https://github.com/walkor/webman/contributors)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 70 - 0
README.md

@@ -0,0 +1,70 @@
+<div style="padding:18px;max-width: 1024px;margin:0 auto;background-color:#fff;color:#333">
+<h1>webman</h1>
+
+基于<a href="https://www.workerman.net" target="__blank">workerman</a>开发的超高性能PHP框架
+
+
+<h1>学习</h1>
+
+<ul>
+  <li>
+    <a href="https://www.workerman.net/webman" target="__blank">主页 / Home page</a>
+  </li>
+  <li>
+    <a href="https://webman.workerman.net" target="__blank">文档 / Document</a>
+  </li>
+  <li>
+    <a href="https://www.workerman.net/doc/webman/install.html" target="__blank">安装 / Install</a>
+  </li>
+  <li>
+    <a href="https://www.workerman.net/questions" target="__blank">问答 / Questions</a>
+  </li>
+  <li>
+    <a href="https://www.workerman.net/apps" target="__blank">市场 / Apps</a>
+  </li>
+  <li>
+    <a href="https://www.workerman.net/sponsor" target="__blank">赞助 / Sponsors</a>
+  </li>
+  <li>
+    <a href="https://www.workerman.net/doc/webman/thanks.html" target="__blank">致谢 / Thanks</a>
+  </li>
+</ul>
+
+<div style="float:left;padding-bottom:30px;">
+
+  <h1>赞助商</h1>
+
+  <h4>特别赞助</h4>
+  <a href="https://www.crmeb.com/?form=workerman" target="__blank">
+    <img src="https://www.workerman.net/img/sponsors/6429/20230719111500.svg" width="200">
+  </a>
+
+  <h4>铂金赞助</h4>
+  <a href="https://www.fadetask.com/?from=workerman" target="__blank"><img src="https://www.workerman.net/img/sponsors/1/20230719084316.png" width="200"></a>
+  <a href="https://www.yilianyun.net/?from=workerman" target="__blank" style="margin-left:20px;"><img src="https://www.workerman.net/img/sponsors/6218/20230720114049.png" width="200"></a>
+
+
+</div>
+
+
+<div style="float:left;padding-bottom:30px;clear:both">
+
+  <h1>请作者喝咖啡</h1>
+
+<img src="https://www.workerman.net/img/wx_donate.png" width="200">
+<img src="https://www.workerman.net/img/ali_donate.png" width="200">
+<br>
+<b>如果您觉得webman对您有所帮助,欢迎捐赠。</b>
+
+
+</div>
+
+
+<div style="clear: both">
+<h1>LICENSE</h1>
+The webman is open-sourced software licensed under the MIT.
+</div>
+
+</div>
+
+

+ 131 - 0
app/command/Model.php

@@ -0,0 +1,131 @@
+<?php
+
+namespace app\command;
+
+use support\think\Db;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use think\db\exception\BindParamException;
+use Webman\Console\Util;
+
+class Model extends Command
+{
+    protected static string $defaultName = 'model:all';
+    protected static string $defaultDescription = '统一生成Model';
+
+    protected function execute(InputInterface $input, OutputInterface $output): int
+    {
+        $output->writeln("生成Model开始====>".getDateFull());
+        try {
+            $table = Db::query("SHOW TABLES");
+        } catch (BindParamException $e) {
+
+        }
+        $connection = config("think-orm.default");
+        $database = config("think-orm.connections.$connection.database");
+        foreach ($table as $val) {
+            $dir = explode("_",$val["Tables_in_{$database}"]);
+            $dirPath = app_path("model").DIRECTORY_SEPARATOR.$dir[0];
+            $namespace = str_replace('/', '\\', 'app/model/' . $dir[0]);
+            $class = Util::nameToClass($val["Tables_in_{$database}"]);
+            $file = $dirPath . DIRECTORY_SEPARATOR . "$class.php";
+            if (file_exists($file)) { // 存在,跳过
+                $output->writeln("已存在,跳过====>".getDateFull()."====>".$file);
+            } else {
+                $path = pathinfo($file, PATHINFO_DIRNAME);
+                if (!is_dir($path)) {
+                    mkdir($path, 0777, true);
+                }
+                $properties = '';
+                $pk = 'id';
+                foreach (Db::query("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '".$val["Tables_in_{$database}"]."' and table_schema = '$database' ORDER BY ordinal_position") as $item) {
+                    if ($item['COLUMN_KEY'] === 'PRI') {
+                        $pk = $item['COLUMN_NAME'];
+                        $item["COLUMN_COMMENT"] .= "(主键)";
+                    }
+                    $type = $this->getType($item["DATA_TYPE"]);
+                    $properties .= " * @property $type \${$item["COLUMN_NAME"]} {$item["COLUMN_COMMENT"]}\n";
+                }
+                $properties = rtrim($properties) ?: ' *';
+                $table_val = $val["Tables_in_{$database}"];
+                $model_content = <<<EOF
+<?php
+
+namespace $namespace;
+
+use app\\extra\\basic\\Model;
+
+
+/**
+$properties
+ */
+class $class extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected \$connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string \$table = "$table_val";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string \$primaryKey = "$pk";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool \$timestamps = false;
+
+
+}
+
+EOF;
+                file_put_contents($file, $model_content);
+                $output->writeln("生成成功====>".getDateFull()."====>".$file);
+            }
+        }
+        return self::SUCCESS;
+    }
+
+
+    protected function getType(string $type): string
+    {
+        if (str_contains($type, 'int')) {
+            return 'integer';
+        }
+        switch ($type) {
+            case 'varchar':
+            case 'string':
+            case 'text':
+            case 'date':
+            case 'time':
+            case 'guid':
+            case 'datetimetz':
+            case 'datetime':
+            case 'decimal':
+            case 'enum':
+                return 'string';
+            case 'boolean':
+                return 'integer';
+            case 'float':
+                return 'float';
+            default:
+                return 'mixed';
+        }
+    }
+
+}

+ 116 - 0
app/command/PoemAuthor.php

@@ -0,0 +1,116 @@
+<?php
+
+namespace app\command;
+
+use app\model\dynasty\Dynasty;
+use app\model\dynasty\DynastyAuthor;
+use Overtrue\Pinyin\Pinyin;
+use QL\QueryList;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use function DI\get;
+
+class PoemAuthor extends Command
+{
+
+    protected static string $defaultName = 'poem:author';
+    protected static string $defaultDescription = '采集作者';
+
+    protected function execute(InputInterface $input, OutputInterface $output): int
+    {
+        try {
+            $nextPage = 1; $done = 0; $subPage = 1;
+            while (is_numeric($nextPage)) {
+                $output->writeln("开始".getDateFull());
+                $resp = (new Dynasty)->where("type",1)->page($nextPage,10)->select();
+                if ($resp->isEmpty()) {
+                    $output->writeln("没有更多任务啦!===".getDateFull());
+                    $nextPage = null;
+                    return self::SUCCESS;
+                }
+                $author = (new DynastyAuthor);
+                foreach ($resp as $key=>$val) {
+                    $output->writeln("朝代:{$val['name']}==页码:{$subPage}===链接地址:https://www.gushiji.cc/shiren/{$val['pinyin']}.html====".getDateFull());
+                    while (is_numeric($subPage)) {
+                        if ($subPage == 1) {
+                            $url = "https://www.gushiji.cc/shiren/{$val['pinyin']}.html";
+                        } else {
+                            $url = "https://www.gushiji.cc/shiren/{$val['pinyin']}_{$subPage}.html";
+                        }
+                        $ql = QueryList::getInstance()->get($url)->rules([
+                            "name"      => ['.simple-people>li','texts'],
+                            "link"      => ['.simple-people>li>a','attrs(href)'],
+                            "avatar"    => ['.simple-people>li>a>img','attrs(src)'],
+                            "page"      => ['#pagenum>li.info','text'],
+                        ])->query()->getData(function ($item,$key){
+                            foreach ($item['avatar'] as $k=>$v){
+                                if (empty($v)){
+                                    $v = "/skin/images/nopicture.jpg";
+                                }
+                                $item['avatar'][$k] = "https://www.gushiji.cc".$v;
+                            }
+                            foreach ($item['link'] as $k=>$v){
+                                $link = explode("/",$v);
+                                $item['link'][$k] = $link[2]??'';
+                            }
+                            $poem = [];
+                            foreach ($item['name'] as $k=>$v){
+                                preg_match('/([^()()]+)[((](\d+)[))]/u', $v, $match);
+                                $item['name'][$k] = $match[1]??'';
+                                $poem[$k] = $match[2]??0;
+                            }
+                            preg_match_all('/\d+/', $item['page'], $matches);
+                            $item['page'] = $matches[0][0] ?? 0;
+                            $item['total'] = $matches[0][1] ?? 0;
+                            $item['poem'] = $poem;
+                            return $item;
+                        });
+                        $respData = $ql->all();
+                        if ($subPage > $respData['page']) {
+                            $output->writeln("朝代:{$val['name']}==没有作者啦==".getDateFull());
+                            $subPage = 1;
+                            break;
+                        }
+                        foreach ($respData['name'] as $k=>$v){
+                            $authorData = $author->where(['name' => $v, 'dynasty_id' => $val['id']])->findOrEmpty();
+                            if ($authorData->isEmpty()) {
+                                $output->writeln("【新增】朝代:{$val['name']}==诗人:{$v}==拼音:".trim($respData['link'][$k])."==".getDateFull());
+                                $authorData->insertGetId([
+                                    "name"          => $v,
+                                    "poem_total"    => $respData['poem'][$k],
+                                    "avatar"        => $respData['avatar'][$k],
+                                    "dynasty_id"    => $val['id'],
+                                    "dynasty_name"  => $val['name'],
+                                    "initial"       => strtoupper(substr($respData['link'][$k], 0, 1)),
+                                    "pinyin"        => $respData['link'][$k]
+                                ]);
+                            } else {
+                                $output->writeln("【更新】朝代:{$val['name']}==诗人:{$v}==拼音:".trim($respData['link'][$k])."==".getDateFull());
+                                $authorData->save([
+                                    "name"          => $v,
+                                    "poem_total"    => $respData['poem'][$k],
+                                    "avatar"        => $respData['avatar'][$k],
+                                    "dynasty_id"    => $val['id'],
+                                    "dynasty_name"  => $val['name'],
+                                    "initial"       => strtoupper(substr($respData['link'][$k], 0, 1)),
+                                    "pinyin"        => $respData['link'][$k]
+                                ]);
+                            }
+                        }
+                        $subPage = $subPage+1;
+                        $output->writeln("进入下一页=={$nextPage}-{$subPage}==".getDateFull());
+                        $output->writeln("===========================================================================");
+                    }
+                }
+                $nextPage = $nextPage+1;
+                $subPage = 1;
+                $output->writeln("进入下一页=={$nextPage}==".getDateFull());
+            }
+        } catch (\Throwable $throwable) {
+
+        }
+        return self::SUCCESS;
+    }
+
+}

+ 99 - 0
app/command/PoemData.php

@@ -0,0 +1,99 @@
+<?php
+
+namespace app\command;
+
+use app\model\dynasty\DynastyAuthor;
+use QL\QueryList;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class PoemData extends Command
+{
+
+    protected static string $defaultName = 'poem:data';
+
+    protected static string $defaultDescription = '采集作者作品列表';
+
+
+    protected function execute(InputInterface $input, OutputInterface $output): int
+    {
+        try {
+            $nextPage = 1; $done = 0; $subPage = 1;
+            while (is_numeric($nextPage)) {
+                $output->writeln("开始" . getDateFull());
+                $resp = (new DynastyAuthor)->page($nextPage,10)->select();
+                if ($resp->isEmpty()) {
+                    $output->writeln("没有更多任务啦!===".getDateFull());
+                    $nextPage = null;
+                    return self::SUCCESS;
+                }
+                $poem = (new \app\model\poem\PoemData);
+                foreach ($resp as $key=>$val) {
+                    while (is_numeric($subPage)) {
+                        if ($subPage == 1) {
+                            $url = "https://www.gushiji.cc/shiren/{$val['pinyin']}/";
+                        } else {
+                            $url = "https://www.gushiji.cc/shiren/{$val['pinyin']}/p{$subPage}.html";
+                        }
+                        $output->writeln("诗人:{$val['name']}==页码:{$subPage}===链接地址:{$url}====".getDateFull());
+                        $ql = QueryList::getInstance()->get($url)->rules([
+                            "page"      => ['#pagenum>li.info','text'],
+                            "name"      => ['.simple-shiciqu>li','texts'],
+                            "link"      => ['.simple-shiciqu>li>a','attrs(href)'],
+                        ])->query()->getData(function ($item,$key){
+                            preg_match_all('/\d+/', $item['page'], $matches);
+                            $item['page'] = $matches[0][0] ?? 0;
+                            $item['total'] = $matches[0][1] ?? 0;
+                            foreach ($item['link'] as $k=>$v){
+                                preg_match('/\/([^\/]+)\.html$/', $v, $match);
+                                $item['link'][$k] = $match[1]??'';
+                            }
+                            return $item;
+                        });
+                        $respData = $ql->all();
+                        if ($subPage > $respData['page']) {
+                            $output->writeln("作者:{$val['name']}==没有作品啦==".getDateFull());
+                            $subPage = 1;
+                            break;
+                        }
+                        foreach ($respData['name'] as $k=>$v) {
+                            $authorData = $poem->where(['poem_id' => $respData['link'][$k]])->findOrEmpty();
+                            if ($authorData->isEmpty()) {
+                                $output->writeln("【新增】作者作品:{$val['name']}==标题:{$v}====".getDateFull());
+                                $authorData->insertGetId([
+                                    "title"         => $v,
+                                    "poem_id"       => $respData['link'][$k],
+                                    "author_id"     => $val['id'],
+                                    "author_name"   => $val['name'],
+                                    "dynasty_id"    => $val['dynasty_id'],
+                                    "dynasty_name"  => $val['dynasty_name'],
+                                ]);
+                            } else {
+                                $output->writeln("【更新】作者作品:{$val['name']}==标题:{$v}====".getDateFull());
+                                $authorData->save([
+                                    "title"         => $v,
+                                    "poem_id"       => $respData['link'][$k],
+                                    "author_id"     => $val['id'],
+                                    "author_name"   => $val['name'],
+                                    "dynasty_id"    => $val['dynasty_id'],
+                                    "dynasty_name"  => $val['dynasty_name'],
+                                ]);
+                            }
+                        }
+                        $subPage = $subPage+1;
+                        $output->writeln("进入下一页=={$nextPage}-{$subPage}==".getDateFull());
+                        $output->writeln("===========================================================================");
+                    }
+                }
+                $nextPage = $nextPage+1;
+                $subPage = 1;
+                $output->writeln("进入下一个作者=={$nextPage}==".getDateFull());
+            }
+        } catch (\Throwable $throwable) {
+            echo $throwable->getMessage()."\n";
+        }
+        return self::SUCCESS;
+    }
+
+}

+ 50 - 0
app/command/ShopwwiAuthCommand.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace app\command;
+
+use Shopwwi\WebmanAuth\Facade\Str;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Output\OutputInterface;
+
+
+class ShopwwiAuthCommand extends Command
+{
+    protected static $defaultName = 'shopwwi:auth';
+    protected static $defaultDescription = 'shopwwi auth';
+
+    /**
+     * @return void
+     */
+    protected function configure()
+    {
+        $this->addArgument('name', InputArgument::OPTIONAL, 'Name description');
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     * @return int
+     */
+    protected function execute(InputInterface $input, OutputInterface $output): int
+    {
+        $name = $input->getArgument('name');
+        $output->writeln('生成jwtKey 开始');
+        $key = Str::random(64);
+        file_put_contents(base_path()."/config/plugin/shopwwi/auth/app.php", str_replace(
+            "'access_secret_key' => '".config('plugin.shopwwi.auth.app.jwt.access_secret_key')."'",
+            "'access_secret_key' => '".$key."'",
+            file_get_contents(base_path()."/config/plugin/shopwwi/auth/app.php")
+        ));
+        file_put_contents(base_path()."/config/plugin/shopwwi/auth/app.php", str_replace(
+            "'refresh_secret_key' => '".config('plugin.shopwwi.auth.app.jwt.refresh_secret_key')."'",
+            "'refresh_secret_key' => '".$key."'",
+            file_get_contents(base_path()."/config/plugin/shopwwi/auth/app.php")
+        ));
+        $output->writeln('生成jwtKey 结束'.$key);
+        return self::SUCCESS;
+    }
+
+}

+ 91 - 0
app/controller/IndexController.php

@@ -0,0 +1,91 @@
+<?php
+
+namespace app\controller;
+
+use app\model\dynasty\DynastyAuthor;
+use app\model\dynasty\DynastyCategory;
+use QL\QueryList;
+use support\Request;
+
+class IndexController
+{
+    public function index(Request $request)
+    {
+        $ql = QueryList::getInstance()->get("https://www.gushiji.cc/dianji/")->rules([
+//            "name"      => ['.gushi-info>h3','texts'],
+//            "link"      => ['.gushi-info>h3>a','attrs(href)'],
+            "name"     => ['.gushi-info>.cipai>ul>li','texts'],
+            "link"      => ['.gushi-info>.cipai>ul>li>a','attrs(href)'],
+        ])->query()->getData(function ($item,$key){
+            foreach ($item['link'] as $k=>$v){
+                $link = explode("/",$v);
+                $item['link'][$k] = $link[2]??'';
+            }
+            return $item;
+        });
+        $resp = $ql->all();
+        foreach ($resp['name'] as $k=>$v){
+            $cate = (new DynastyAuthor)->where("pinyin",$resp['link'][$k])->findOrEmpty();
+            if ($cate->isEmpty()){
+                $cate->insertGetId([
+                    "pinyin"    => $resp['link'][$k],
+                    "name"      => $v,
+                    "type"      => 2,
+                    "initial"       => strtoupper(substr($resp['link'][$k], 0, 1)),
+                ]);
+            } else {
+                $cate->insertGetId([
+                    "pinyin"    => $resp['link'][$k],
+                    "name"      => $v,
+                    "type"      => 2,
+                    "initial"       => strtoupper(substr($resp['link'][$k], 0, 1)),
+                ]);
+            }
+        }
+        return json($resp);
+    }
+
+    protected function getAuthor()
+    {
+        $ql = QueryList::getInstance()->get("https://www.gushiji.cc/shiren/")->rules([
+            "name"      => ['.simple-people>li','texts'],
+            "link"      => ['.simple-people>li>a','attrs(href)'],
+            "avatar"    => ['.simple-people>li>a>img','attrs(src)'],
+            "page"      => ['#pagenum>li.info','text'],
+        ])->query()->getData(function ($item,$key){
+            foreach ($item['avatar'] as $k=>$v){
+                if (empty($v)){
+                    $v = "/skin/images/nopicture.jpg";
+                }
+                $item['avatar'][$k] = "https://www.gushiji.cc".$v;
+            }
+            foreach ($item['link'] as $k=>$v){
+                $link = explode("/",$v);
+                $item['link'][$k] = $link[2]??'';
+            }
+            $poem = [];
+            foreach ($item['name'] as $k=>$v){
+                preg_match('/([^()()]+)[((](\d+)[))]/u', $v, $match);
+                $item['name'][$k] = $match[1]??'';
+                $poem[$k] = $match[2]??0;
+            }
+            preg_match_all('/\d+/', $item['page'], $matches);
+            $item['page'] = $matches[0][0] ?? 0;
+            $item['total'] = $matches[0][1] ?? 0;
+            $item['poem'] = $poem;
+            return $item;
+        });
+        return $ql->all();
+    }
+
+    public function view(Request $request)
+    {
+        return view('index/view', ['name' => 'webman']);
+    }
+
+    public function json(Request $request)
+    {
+        return json(['code' => 0, 'msg' => 'ok']);
+    }
+
+}

+ 29 - 0
app/extra/basic/Model.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace app\extra\basic;
+
+class Model extends \think\Model
+{
+
+    /**
+     * 数据操作
+     * @param array $data
+     * @param string $id
+     * @return bool|int
+     */
+    public function setAutoData(array $data = [],string $id = "id"): bool|int
+    {
+        try {
+            if (isset($data[$id]) && $this->where($id,$data[$id])->count()) {
+                $state = $this->where($id,$data[$id])->strict(false)->update($data);
+            } else {
+                $state = $this->strict(false)->insertGetId($data);
+            }
+        } catch (\Throwable $throwable) {
+            echo $throwable->getMessage()."\n";
+            return false;
+        }
+        return $state;
+    }
+
+}

+ 74 - 0
app/functions.php

@@ -0,0 +1,74 @@
+<?php
+
+
+use support\Response;
+use Webman\Event\Event;
+
+if (!function_exists("getDateFull"))
+{
+    /**
+     * @param string $format
+     * @param string $time
+     * @return string
+     */
+    function getDateFull(string $format = "Y-m-d H:i:s",string $time = ""): string
+    {
+        if (empty($time)) $time = time();
+        return date($format??'Y-m-d H:i:s',$time);
+    }
+}
+
+if (!function_exists("events"))
+{
+    /**
+     * 事件发布
+     * @param $name
+     * @param $data
+     * @return array|mixed|null
+     */
+    function events($name,$data): mixed
+    {
+        return Event::dispatch($name,$data);
+    }
+}
+
+if (!function_exists("_json")) {
+    /**
+     * @param string $msg
+     * @param array $data
+     * @param int $code
+     * @return Response
+     */
+    function _json(int $code = 1, string $msg = "", array $data = []): Response
+    {
+        return json(compact('code', 'data', 'msg'));
+    }
+}
+
+if (!function_exists("pageFormat")) {
+    /**
+     * @param $data
+     * @param int $size
+     * @return array {page:"",pageSize:"",rows:[],total:""}
+     */
+    function pageFormat($data, int $size = 10): array
+    {
+        if (empty($data)) return [];
+        return [
+            'total'     => $data->total(),
+            'page'      => $data->currentPage(),
+            'pageSize'  => $size,
+            'rows'      => $data->items()
+        ];
+    }
+}
+
+if(!function_exists('format_money')){
+    function format_money($str,$len = '2',$append = ""): string
+    {
+        if (empty($str)) {
+            return "0.00";
+        }
+        return number_format($str, $len, ".", $append);
+    }
+}

+ 42 - 0
app/middleware/StaticFile.php

@@ -0,0 +1,42 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+namespace app\middleware;
+
+use Webman\MiddlewareInterface;
+use Webman\Http\Response;
+use Webman\Http\Request;
+
+/**
+ * Class StaticFile
+ * @package app\middleware
+ */
+class StaticFile implements MiddlewareInterface
+{
+    public function process(Request $request, callable $handler): Response
+    {
+        // Access to files beginning with. Is prohibited
+        if (strpos($request->path(), '/.') !== false) {
+            return response('<h1>403 forbidden</h1>', 403);
+        }
+        /** @var Response $response */
+        $response = $handler($request);
+        // Add cross domain HTTP header
+        /*$response->withHeaders([
+            'Access-Control-Allow-Origin'      => '*',
+            'Access-Control-Allow-Credentials' => 'true',
+        ]);*/
+        return $response;
+    }
+}

+ 50 - 0
app/model/dynasty/Dynasty.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace app\model\dynasty;
+
+use app\extra\basic\Model;
+
+
+/**
+ * @property integer $id (主键)
+ * @property string $name 
+ * @property string $sub_name 
+ * @property integer $poem_total 诗词数量
+ * @property integer $author_total 作者数量
+ * @property integer $status 
+ * @property string $pinyin 
+ * @property integer $type 1朝代2古籍
+ * @property mixed $create_at
+ */
+class Dynasty extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "dynasty";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+
+}

+ 50 - 0
app/model/dynasty/DynastyAuthor.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace app\model\dynasty;
+
+use app\extra\basic\Model;
+
+
+/**
+ * @property integer $id (主键)
+ * @property string $name 
+ * @property integer $poem_total 诗词数量
+ * @property integer $dynasty_id 
+ * @property mixed $dynasty_name 
+ * @property mixed $initial 首字母
+ * @property string $pinyin 名字拼音
+ * @property integer $status 
+ * @property mixed $create_at
+ */
+class DynastyAuthor extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "dynasty_author";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+
+}

+ 42 - 0
app/model/dynasty/DynastyAuthorInfo.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace app\model\dynasty;
+
+use app\extra\basic\Model;
+
+
+/**
+ * @property integer $id (主键)
+ */
+class DynastyAuthorInfo extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "dynasty_author_info";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+
+}

+ 47 - 0
app/model/dynasty/DynastyCategory.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace app\model\dynasty;
+
+use app\extra\basic\Model;
+
+
+/**
+ * @property integer $id (主键)
+ * @property integer $parent_id 
+ * @property string $name 
+ * @property string $pinyin 
+ * @property integer $status 
+ * @property mixed $create_at
+ */
+class DynastyCategory extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "dynasty_category";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+
+}

+ 48 - 0
app/model/poem/PoemData.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace app\model\poem;
+
+use app\extra\basic\Model;
+
+
+/**
+ * @property integer $id (主键)
+ * @property string $title 标题
+ * @property mixed $poem_id 随机ID
+ * @property integer $author_id 作者ID
+ * @property mixed $author_name 作者名称
+ * @property integer $dynasty_id 朝代ID
+ * @property mixed $dynasty_name 朝代名称
+ */
+class PoemData extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "poem_data";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+
+}

+ 10 - 0
app/process/Http.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace app\process;
+
+use Webman\App;
+
+class Http extends App
+{
+
+}

+ 305 - 0
app/process/Monitor.php

@@ -0,0 +1,305 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+namespace app\process;
+
+use FilesystemIterator;
+use RecursiveDirectoryIterator;
+use RecursiveIteratorIterator;
+use SplFileInfo;
+use Workerman\Timer;
+use Workerman\Worker;
+
+/**
+ * Class FileMonitor
+ * @package process
+ */
+class Monitor
+{
+    /**
+     * @var array
+     */
+    protected array $paths = [];
+
+    /**
+     * @var array
+     */
+    protected array $extensions = [];
+
+    /**
+     * @var array
+     */
+    protected array $loadedFiles = [];
+
+    /**
+     * @var int
+     */
+    protected int $ppid = 0;
+
+    /**
+     * Pause monitor
+     * @return void
+     */
+    public static function pause(): void
+    {
+        file_put_contents(static::lockFile(), time());
+    }
+
+    /**
+     * Resume monitor
+     * @return void
+     */
+    public static function resume(): void
+    {
+        clearstatcache();
+        if (is_file(static::lockFile())) {
+            unlink(static::lockFile());
+        }
+    }
+
+    /**
+     * Whether monitor is paused
+     * @return bool
+     */
+    public static function isPaused(): bool
+    {
+        clearstatcache();
+        return file_exists(static::lockFile());
+    }
+
+    /**
+     * Lock file
+     * @return string
+     */
+    protected static function lockFile(): string
+    {
+        return runtime_path('monitor.lock');
+    }
+
+    /**
+     * FileMonitor constructor.
+     * @param $monitorDir
+     * @param $monitorExtensions
+     * @param array $options
+     */
+    public function __construct($monitorDir, $monitorExtensions, array $options = [])
+    {
+        $this->ppid = function_exists('posix_getppid') ? posix_getppid() : 0;
+        static::resume();
+        $this->paths = (array)$monitorDir;
+        $this->extensions = $monitorExtensions;
+        foreach (get_included_files() as $index => $file) {
+            $this->loadedFiles[$file] = $index;
+            if (strpos($file, 'webman-framework/src/support/App.php')) {
+                break;
+            }
+        }
+        if (!Worker::getAllWorkers()) {
+            return;
+        }
+        $disableFunctions = explode(',', ini_get('disable_functions'));
+        if (in_array('exec', $disableFunctions, true)) {
+            echo "\nMonitor file change turned off because exec() has been disabled by disable_functions setting in " . PHP_CONFIG_FILE_PATH . "/php.ini\n";
+        } else {
+            if ($options['enable_file_monitor'] ?? true) {
+                Timer::add(1, function () {
+                    $this->checkAllFilesChange();
+                });
+            }
+        }
+
+        $memoryLimit = $this->getMemoryLimit($options['memory_limit'] ?? null);
+        if ($memoryLimit && ($options['enable_memory_monitor'] ?? true)) {
+            Timer::add(60, [$this, 'checkMemory'], [$memoryLimit]);
+        }
+    }
+
+    /**
+     * @param $monitorDir
+     * @return bool
+     */
+    public function checkFilesChange($monitorDir): bool
+    {
+        static $lastMtime, $tooManyFilesCheck;
+        if (!$lastMtime) {
+            $lastMtime = time();
+        }
+        clearstatcache();
+        if (!is_dir($monitorDir)) {
+            if (!is_file($monitorDir)) {
+                return false;
+            }
+            $iterator = [new SplFileInfo($monitorDir)];
+        } else {
+            // recursive traversal directory
+            $dirIterator = new RecursiveDirectoryIterator($monitorDir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS);
+            $iterator = new RecursiveIteratorIterator($dirIterator);
+        }
+        $count = 0;
+        foreach ($iterator as $file) {
+            $count ++;
+            /** @var SplFileInfo $file */
+            if (is_dir($file->getRealPath())) {
+                continue;
+            }
+            // check mtime
+            if (in_array($file->getExtension(), $this->extensions, true) && $lastMtime < $file->getMTime()) {
+                $lastMtime = $file->getMTime();
+                if (DIRECTORY_SEPARATOR === '/' && isset($this->loadedFiles[$file->getRealPath()])) {
+                    echo "$file updated but cannot be reloaded because only auto-loaded files support reload.\n";
+                    continue;
+                }
+                $var = 0;
+                exec('"'.PHP_BINARY . '" -l ' . $file, $out, $var);
+                if ($var) {
+                    continue;
+                }
+                // send SIGUSR1 signal to master process for reload
+                if (DIRECTORY_SEPARATOR === '/') {
+                    if ($masterPid = $this->getMasterPid()) {
+                        echo $file . " updated and reload\n";
+                        posix_kill($masterPid, SIGUSR1);
+                    } else {
+                        echo "Master process has gone away and can not reload\n";
+                    }
+                    return true;
+                }
+                echo $file . " updated and reload\n";
+                return true;
+            }
+        }
+        if (!$tooManyFilesCheck && $count > 1000) {
+            echo "Monitor: There are too many files ($count files) in $monitorDir which makes file monitoring very slow\n";
+            $tooManyFilesCheck = 1;
+        }
+        return false;
+    }
+
+    /**
+     * @return int
+     */
+    public function getMasterPid(): int
+    {
+        if ($this->ppid === 0) {
+            return 0;
+        }
+        if (function_exists('posix_kill') && !posix_kill($this->ppid, 0)) {
+            echo "Master process has gone away\n";
+            return $this->ppid = 0;
+        }
+        if (PHP_OS_FAMILY !== 'Linux') {
+            return $this->ppid;
+        }
+        $cmdline = "/proc/$this->ppid/cmdline";
+        if (!is_readable($cmdline) || !($content = file_get_contents($cmdline)) || (!str_contains($content, 'WorkerMan') && !str_contains($content, 'php'))) {
+            // Process not exist
+            $this->ppid = 0;
+        }
+        return $this->ppid;
+    }
+
+    /**
+     * @return bool
+     */
+    public function checkAllFilesChange(): bool
+    {
+        if (static::isPaused()) {
+            return false;
+        }
+        foreach ($this->paths as $path) {
+            if ($this->checkFilesChange($path)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @param $memoryLimit
+     * @return void
+     */
+    public function checkMemory($memoryLimit): void
+    {
+        if (static::isPaused() || $memoryLimit <= 0) {
+            return;
+        }
+        $masterPid = $this->getMasterPid();
+        if ($masterPid <= 0) {
+            echo "Master process has gone away\n";
+            return;
+        }
+
+        $childrenFile = "/proc/$masterPid/task/$masterPid/children";
+        if (!is_file($childrenFile) || !($children = file_get_contents($childrenFile))) {
+            return;
+        }
+        foreach (explode(' ', $children) as $pid) {
+            $pid = (int)$pid;
+            $statusFile = "/proc/$pid/status";
+            if (!is_file($statusFile) || !($status = file_get_contents($statusFile))) {
+                continue;
+            }
+            $mem = 0;
+            if (preg_match('/VmRSS\s*?:\s*?(\d+?)\s*?kB/', $status, $match)) {
+                $mem = $match[1];
+            }
+            $mem = (int)($mem / 1024);
+            if ($mem >= $memoryLimit) {
+                posix_kill($pid, SIGINT);
+            }
+        }
+    }
+
+    /**
+     * Get memory limit
+     * @param $memoryLimit
+     * @return int
+     */
+    protected function getMemoryLimit($memoryLimit): int
+    {
+        if ($memoryLimit === 0) {
+            return 0;
+        }
+        $usePhpIni = false;
+        if (!$memoryLimit) {
+            $memoryLimit = ini_get('memory_limit');
+            $usePhpIni = true;
+        }
+
+        if ($memoryLimit == -1) {
+            return 0;
+        }
+        $unit = strtolower($memoryLimit[strlen($memoryLimit) - 1]);
+        $memoryLimit = (int)$memoryLimit;
+        if ($unit === 'g') {
+            $memoryLimit = 1024 * $memoryLimit;
+        } else if ($unit === 'k') {
+            $memoryLimit = ($memoryLimit / 1024);
+        } else if ($unit === 'm') {
+            $memoryLimit = (int)($memoryLimit);
+        } else if ($unit === 't') {
+            $memoryLimit = (1024 * 1024 * $memoryLimit);
+        } else {
+            $memoryLimit = ($memoryLimit / (1024 * 1024));
+        }
+        if ($memoryLimit < 50) {
+            $memoryLimit = 50;
+        }
+        if ($usePhpIni) {
+            $memoryLimit = (0.8 * $memoryLimit);
+        }
+        return (int)$memoryLimit;
+    }
+
+}

+ 14 - 0
app/view/index/view.html

@@ -0,0 +1,14 @@
+<!doctype html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="shortcut icon" href="/favicon.ico"/>
+    <title>webman</title>
+
+</head>
+<body>
+hello <?=htmlspecialchars($name)?>
+</body>
+</html>

+ 82 - 0
composer.json

@@ -0,0 +1,82 @@
+{
+  "name": "workerman/webman",
+  "type": "project",
+  "keywords": [
+    "high performance",
+    "http service"
+  ],
+  "homepage": "https://www.workerman.net",
+  "license": "MIT",
+  "description": "High performance HTTP Service Framework.",
+  "authors": [
+    {
+      "name": "walkor",
+      "email": "walkor@workerman.net",
+      "homepage": "https://www.workerman.net",
+      "role": "Developer"
+    }
+  ],
+  "support": {
+    "email": "walkor@workerman.net",
+    "issues": "https://github.com/walkor/webman/issues",
+    "forum": "https://wenda.workerman.net/",
+    "wiki": "https://workerman.net/doc/webman",
+    "source": "https://github.com/walkor/webman"
+  },
+  "require": {
+    "php": ">=8.1",
+    "workerman/webman-framework": "^2.1",
+    "monolog/monolog": "^2.0",
+    "webman/console": "^2.2",
+    "webman/think-orm": "^2.1",
+    "webman/redis": "^2.1",
+    "illuminate/events": "^12.64",
+    "webman/validation": "^2.2",
+    "shopwwi/webman-auth": "^2.0",
+    "tinywan/storage": "^1.1",
+    "aliyuncs/oss-sdk-php": "^2.7",
+    "qcloud/cos-sdk-v5": "^2.6",
+    "webman/think-cache": "^2.1",
+    "webman/redis-queue": "^2.1",
+    "webman/event": "^1.0",
+    "yzh52521/easyhttp": "^1.1",
+    "linfly/annotation": "^2.1",
+    "vlucas/phpdotenv": "^5.6",
+    "workerman/crontab": "^1.0",
+    "phpoffice/phpspreadsheet": "^5.9",
+    "symfony/translation": "^7.4",
+    "php-di/php-di": "^7.0",
+    "jaeger/querylist": "^4.4",
+    "overtrue/pinyin": "^6.0"
+  },
+  "suggest": {
+    "ext-event": "For better performance. "
+  },
+  "autoload": {
+    "psr-4": {
+      "": "./",
+      "app\\": "./app",
+      "App\\": "./app",
+      "app\\View\\Components\\": "./app/view/components"
+    }
+  },
+  "scripts": {
+    "post-package-install": [
+      "support\\Plugin::install"
+    ],
+    "post-package-update": [
+      "support\\Plugin::install"
+    ],
+    "pre-package-uninstall": [
+      "support\\Plugin::uninstall"
+    ],
+    "post-create-project-cmd": [
+      "support\\Setup::run"
+    ],
+    "setup-webman": [
+      "support\\Setup::run"
+    ]
+  },
+  "minimum-stability": "dev",
+  "prefer-stable": true
+}

+ 5350 - 0
composer.lock

@@ -0,0 +1,5350 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "d0ea14f19b87b3f732c3ee59e1af7881",
+    "packages": [
+        {
+            "name": "aliyuncs/oss-sdk-php",
+            "version": "v2.7.3",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/aliyuncs/oss-sdk-php/v2.7.3/aliyuncs-oss-sdk-php-v2.7.3.zip",
+                "reference": "10dbd2a7253131da60629d431c8eb6c216fbbbf7",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3"
+            },
+            "require-dev": {
+                "php-coveralls/php-coveralls": "*",
+                "phpunit/phpunit": "*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "OSS\\": "src/OSS"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Aliyuncs",
+                    "homepage": "http://www.aliyun.com"
+                }
+            ],
+            "description": "Aliyun OSS SDK for PHP",
+            "homepage": "http://www.aliyun.com/product/oss/",
+            "support": {
+                "issues": "https://github.com/aliyun/aliyun-oss-php-sdk/issues",
+                "source": "https://github.com/aliyun/aliyun-oss-php-sdk/tree/v2.7.3"
+            },
+            "time": "2026-06-26T07:23:48+00:00"
+        },
+        {
+            "name": "brick/math",
+            "version": "0.14.8",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/brick/math/0.14.8/brick-math-0.14.8.zip",
+                "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^8.2"
+            },
+            "require-dev": {
+                "php-coveralls/php-coveralls": "^2.2",
+                "phpstan/phpstan": "2.1.22",
+                "phpunit/phpunit": "^11.5"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Brick\\Math\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "description": "Arbitrary-precision arithmetic library",
+            "keywords": [
+                "Arbitrary-precision",
+                "BigInteger",
+                "BigRational",
+                "arithmetic",
+                "bigdecimal",
+                "bignum",
+                "bignumber",
+                "brick",
+                "decimal",
+                "integer",
+                "math",
+                "mathematics",
+                "rational"
+            ],
+            "support": {
+                "issues": "https://github.com/brick/math/issues",
+                "source": "https://github.com/brick/math/tree/0.14.8"
+            },
+            "time": "2026-02-10T14:33:43+00:00"
+        },
+        {
+            "name": "carbonphp/carbon-doctrine-types",
+            "version": "3.2.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/carbonphp/carbon-doctrine-types/3.2.0/carbonphp-carbon-doctrine-types-3.2.0.zip",
+                "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^8.1"
+            },
+            "conflict": {
+                "doctrine/dbal": "<4.0.0 || >=5.0.0"
+            },
+            "require-dev": {
+                "doctrine/dbal": "^4.0.0",
+                "nesbot/carbon": "^2.71.0 || ^3.0.0",
+                "phpunit/phpunit": "^10.3"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Carbon\\Doctrine\\": "src/Carbon/Doctrine/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "KyleKatarn",
+                    "email": "kylekatarnls@gmail.com"
+                }
+            ],
+            "description": "Types to use Carbon in Doctrine",
+            "keywords": [
+                "carbon",
+                "date",
+                "datetime",
+                "doctrine",
+                "time"
+            ],
+            "support": {
+                "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues",
+                "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0"
+            },
+            "time": "2024-02-09T16:56:22+00:00"
+        },
+        {
+            "name": "composer/pcre",
+            "version": "3.4.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/composer/pcre/3.4.0/composer-pcre-3.4.0.zip",
+                "reference": "d5a341b3fb61f3001970940afb1d332968a183ed",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.4 || ^8.0"
+            },
+            "conflict": {
+                "phpstan/phpstan": "<2.2.2"
+            },
+            "require-dev": {
+                "phpstan/phpstan": "^2",
+                "phpstan/phpstan-deprecation-rules": "^2",
+                "phpstan/phpstan-strict-rules": "^2",
+                "phpunit/phpunit": "^9"
+            },
+            "type": "library",
+            "extra": {
+                "phpstan": {
+                    "includes": [
+                        "extension.neon"
+                    ]
+                },
+                "branch-alias": {
+                    "dev-main": "3.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Composer\\Pcre\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jordi Boggiano",
+                    "email": "j.boggiano@seld.be",
+                    "homepage": "http://seld.be"
+                }
+            ],
+            "description": "PCRE wrapping library that offers type-safe preg_* replacements.",
+            "keywords": [
+                "PCRE",
+                "preg",
+                "regex",
+                "regular expression"
+            ],
+            "support": {
+                "issues": "https://github.com/composer/pcre/issues",
+                "source": "https://github.com/composer/pcre/tree/3.4.0"
+            },
+            "time": "2026-06-07T11:47:49+00:00"
+        },
+        {
+            "name": "doctrine/inflector",
+            "version": "2.1.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/doctrine/inflector/2.1.0/doctrine-inflector-2.1.0.zip",
+                "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2 || ^8.0"
+            },
+            "require-dev": {
+                "doctrine/coding-standard": "^12.0 || ^13.0",
+                "phpstan/phpstan": "^1.12 || ^2.0",
+                "phpstan/phpstan-phpunit": "^1.4 || ^2.0",
+                "phpstan/phpstan-strict-rules": "^1.6 || ^2.0",
+                "phpunit/phpunit": "^8.5 || ^12.2"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Doctrine\\Inflector\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Benjamin Eberlei",
+                    "email": "kontakt@beberlei.de"
+                },
+                {
+                    "name": "Jonathan Wage",
+                    "email": "jonwage@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
+            "homepage": "https://www.doctrine-project.org/projects/inflector.html",
+            "keywords": [
+                "inflection",
+                "inflector",
+                "lowercase",
+                "manipulation",
+                "php",
+                "plural",
+                "singular",
+                "strings",
+                "uppercase",
+                "words"
+            ],
+            "support": {
+                "issues": "https://github.com/doctrine/inflector/issues",
+                "source": "https://github.com/doctrine/inflector/tree/2.1.0"
+            },
+            "time": "2025-08-10T19:31:58+00:00"
+        },
+        {
+            "name": "doctrine/lexer",
+            "version": "3.0.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/doctrine/lexer/3.0.1/doctrine-lexer-3.0.1.zip",
+                "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^8.1"
+            },
+            "require-dev": {
+                "doctrine/coding-standard": "^12",
+                "phpstan/phpstan": "^1.10",
+                "phpunit/phpunit": "^10.5",
+                "psalm/plugin-phpunit": "^0.18.3",
+                "vimeo/psalm": "^5.21"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Doctrine\\Common\\Lexer\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
+            "homepage": "https://www.doctrine-project.org/projects/lexer.html",
+            "keywords": [
+                "annotations",
+                "docblock",
+                "lexer",
+                "parser",
+                "php"
+            ],
+            "support": {
+                "issues": "https://github.com/doctrine/lexer/issues",
+                "source": "https://github.com/doctrine/lexer/tree/3.0.1"
+            },
+            "time": "2024-02-05T11:56:58+00:00"
+        },
+        {
+            "name": "egulias/email-validator",
+            "version": "4.0.4",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/egulias/email-validator/4.0.4/egulias-email-validator-4.0.4.zip",
+                "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/lexer": "^2.0 || ^3.0",
+                "php": ">=8.1",
+                "symfony/polyfill-intl-idn": "^1.26"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^10.2",
+                "vimeo/psalm": "^5.12"
+            },
+            "suggest": {
+                "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Egulias\\EmailValidator\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Eduardo Gulias Davis"
+                }
+            ],
+            "description": "A library for validating emails against several RFCs",
+            "homepage": "https://github.com/egulias/EmailValidator",
+            "keywords": [
+                "email",
+                "emailvalidation",
+                "emailvalidator",
+                "validation",
+                "validator"
+            ],
+            "support": {
+                "issues": "https://github.com/egulias/EmailValidator/issues",
+                "source": "https://github.com/egulias/EmailValidator/tree/4.0.4"
+            },
+            "time": "2025-03-06T22:45:56+00:00"
+        },
+        {
+            "name": "firebase/php-jwt",
+            "version": "v7.1.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/firebase/php-jwt/v7.1.0/firebase-php-jwt-v7.1.0.zip",
+                "reference": "b374a5d1a4f1f67fadc2165cdb284645945e2fc0",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^8.0"
+            },
+            "require-dev": {
+                "guzzlehttp/guzzle": "^7.4",
+                "phpfastcache/phpfastcache": "^9.2",
+                "phpseclib/phpseclib": "~3.0",
+                "phpspec/prophecy-phpunit": "^2.0",
+                "phpunit/phpunit": "^9.5",
+                "psr/cache": "^2.0||^3.0",
+                "psr/http-client": "^1.0",
+                "psr/http-factory": "^1.0"
+            },
+            "suggest": {
+                "ext-sodium": "Support EdDSA (Ed25519) signatures",
+                "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present",
+                "phpseclib/phpseclib": "Support PS256 (RSASSA-PSS) signatures"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Firebase\\JWT\\": "src"
+                }
+            },
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Neuman Vong",
+                    "email": "neuman+pear@twilio.com",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Anant Narayanan",
+                    "email": "anant@php.net",
+                    "role": "Developer"
+                }
+            ],
+            "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
+            "homepage": "https://github.com/googleapis/php-jwt",
+            "keywords": [
+                "jwt",
+                "php"
+            ],
+            "support": {
+                "issues": "https://github.com/googleapis/php-jwt/issues",
+                "source": "https://github.com/googleapis/php-jwt/tree/v7.1.0"
+            },
+            "time": "2026-06-11T17:54:14+00:00"
+        },
+        {
+            "name": "graham-campbell/result-type",
+            "version": "v1.1.4",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/graham-campbell/result-type/v1.1.4/graham-campbell-result-type-v1.1.4.zip",
+                "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2.5 || ^8.0",
+                "phpoption/phpoption": "^1.9.5"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "GrahamCampbell\\ResultType\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                }
+            ],
+            "description": "An Implementation Of The Result Type",
+            "keywords": [
+                "Graham Campbell",
+                "GrahamCampbell",
+                "Result Type",
+                "Result-Type",
+                "result"
+            ],
+            "support": {
+                "issues": "https://github.com/GrahamCampbell/Result-Type/issues",
+                "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4"
+            },
+            "time": "2025-12-27T19:43:20+00:00"
+        },
+        {
+            "name": "guzzlehttp/command",
+            "version": "1.5.3",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/command/1.5.3/guzzlehttp-command-1.5.3.zip",
+                "reference": "5bf05727052d6d16617b2215e3a2307229332026",
+                "shasum": ""
+            },
+            "require": {
+                "guzzlehttp/guzzle": "^7.15",
+                "guzzlehttp/promises": "^2.5.1",
+                "guzzlehttp/psr7": "^2.13",
+                "php": "^7.2.5 || ^8.0",
+                "symfony/deprecation-contracts": "^2.5 || ^3.0"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.2",
+                "phpunit/phpunit": "^8.5.52 || ^9.6.34"
+            },
+            "type": "library",
+            "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "GuzzleHttp\\Command\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "Jeremy Lindblom",
+                    "email": "jeremeamia@gmail.com",
+                    "homepage": "https://github.com/jeremeamia"
+                },
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com",
+                    "homepage": "https://github.com/Nyholm"
+                }
+            ],
+            "description": "Provides the foundation for building command-based web service clients",
+            "support": {
+                "issues": "https://github.com/guzzle/command/issues",
+                "source": "https://github.com/guzzle/command/tree/1.5.3"
+            },
+            "time": "2026-07-17T12:30:59+00:00"
+        },
+        {
+            "name": "guzzlehttp/guzzle",
+            "version": "7.15.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/guzzle/7.15.1/guzzlehttp-guzzle-7.15.1.zip",
+                "reference": "61443dfb33c62f308ee8add20f45b4d6e4bf8d2f",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "guzzlehttp/promises": "^2.5.1",
+                "guzzlehttp/psr7": "^2.13",
+                "php": "^7.2.5 || ^8.0",
+                "psr/http-client": "^1.0",
+                "symfony/deprecation-contracts": "^2.5 || ^3.0",
+                "symfony/polyfill-php80": "^1.25"
+            },
+            "provide": {
+                "psr/http-client-implementation": "1.0"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.2",
+                "ext-curl": "*",
+                "guzzle/client-integration-tests": "3.0.3",
+                "guzzlehttp/test-server": "^0.7",
+                "php-http/message-factory": "^1.1",
+                "phpunit/phpunit": "^8.5.52 || ^9.6.34",
+                "psr/log": "^1.1 || ^2.0 || ^3.0"
+            },
+            "suggest": {
+                "ext-curl": "Required for CURL handler support",
+                "ext-intl": "Required for Internationalized Domain Name (IDN) support",
+                "psr/log": "Required for using the Log middleware"
+            },
+            "type": "library",
+            "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                }
+            },
+            "autoload": {
+                "files": [
+                    "src/functions_include.php"
+                ],
+                "psr-4": {
+                    "GuzzleHttp\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "Jeremy Lindblom",
+                    "email": "jeremeamia@gmail.com",
+                    "homepage": "https://github.com/jeremeamia"
+                },
+                {
+                    "name": "George Mponos",
+                    "email": "gmponos@gmail.com",
+                    "homepage": "https://github.com/gmponos"
+                },
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com",
+                    "homepage": "https://github.com/Nyholm"
+                },
+                {
+                    "name": "Márk Sági-Kazár",
+                    "email": "mark.sagikazar@gmail.com",
+                    "homepage": "https://github.com/sagikazarmark"
+                },
+                {
+                    "name": "Tobias Schultze",
+                    "email": "webmaster@tubo-world.de",
+                    "homepage": "https://github.com/Tobion"
+                }
+            ],
+            "description": "Guzzle is a PHP HTTP client library",
+            "keywords": [
+                "client",
+                "curl",
+                "framework",
+                "http",
+                "http client",
+                "psr-18",
+                "psr-7",
+                "rest",
+                "web service"
+            ],
+            "support": {
+                "issues": "https://github.com/guzzle/guzzle/issues",
+                "source": "https://github.com/guzzle/guzzle/tree/7.15.1"
+            },
+            "time": "2026-07-18T11:23:11+00:00"
+        },
+        {
+            "name": "guzzlehttp/guzzle-services",
+            "version": "1.7.3",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/guzzle-services/1.7.3/guzzlehttp-guzzle-services-1.7.3.zip",
+                "reference": "5d365c5adbc04c76c164a0bc09780323d02c39c0",
+                "shasum": ""
+            },
+            "require": {
+                "guzzlehttp/command": "^1.5.3",
+                "guzzlehttp/guzzle": "^7.15",
+                "guzzlehttp/psr7": "^2.13",
+                "guzzlehttp/uri-template": "^1.0.10",
+                "php": "^7.2.5 || ^8.0",
+                "symfony/deprecation-contracts": "^2.5 || ^3.0",
+                "symfony/polyfill-php80": "^1.25"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.2",
+                "guzzlehttp/test-server": "^0.5",
+                "phpunit/phpunit": "^8.5.52 || ^9.6.34"
+            },
+            "suggest": {
+                "gimler/guzzle-description-loader": "^0.0.4"
+            },
+            "type": "library",
+            "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "GuzzleHttp\\Command\\Guzzle\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "Stefano Kowalke",
+                    "email": "blueduck@mail.org",
+                    "homepage": "https://github.com/Konafets"
+                },
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com",
+                    "homepage": "https://github.com/Nyholm"
+                }
+            ],
+            "description": "Provides an implementation of the Guzzle Command library that uses Guzzle service descriptions to describe web services, serialize requests, and parse responses into easy to use model structures.",
+            "support": {
+                "issues": "https://github.com/guzzle/guzzle-services/issues",
+                "source": "https://github.com/guzzle/guzzle-services/tree/1.7.3"
+            },
+            "time": "2026-07-17T14:26:46+00:00"
+        },
+        {
+            "name": "guzzlehttp/promises",
+            "version": "2.5.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/promises/2.5.1/guzzlehttp-promises-2.5.1.zip",
+                "reference": "9ad1e4fc607446a055b95870c7f668e93b5cff29",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2.5 || ^8.0",
+                "symfony/deprecation-contracts": "^2.5 || ^3.0"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.2",
+                "phpunit/phpunit": "^8.5.52 || ^9.6.34"
+            },
+            "type": "library",
+            "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "GuzzleHttp\\Promise\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com",
+                    "homepage": "https://github.com/Nyholm"
+                },
+                {
+                    "name": "Tobias Schultze",
+                    "email": "webmaster@tubo-world.de",
+                    "homepage": "https://github.com/Tobion"
+                }
+            ],
+            "description": "Guzzle promises library",
+            "keywords": [
+                "promise"
+            ],
+            "support": {
+                "issues": "https://github.com/guzzle/promises/issues",
+                "source": "https://github.com/guzzle/promises/tree/2.5.1"
+            },
+            "time": "2026-07-08T15:48:39+00:00"
+        },
+        {
+            "name": "guzzlehttp/psr7",
+            "version": "2.13.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/psr7/2.13.0/guzzlehttp-psr7-2.13.0.zip",
+                "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2.5 || ^8.0",
+                "psr/http-factory": "^1.0",
+                "psr/http-message": "^1.1 || ^2.0",
+                "ralouphie/getallheaders": "^3.0",
+                "symfony/deprecation-contracts": "^2.5 || ^3.0",
+                "symfony/polyfill-php80": "^1.25"
+            },
+            "provide": {
+                "psr/http-factory-implementation": "1.0",
+                "psr/http-message-implementation": "1.0"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.2",
+                "http-interop/http-factory-tests": "1.1.0",
+                "jshttp/mime-db": "1.54.0.1",
+                "phpunit/phpunit": "^8.5.52 || ^9.6.34"
+            },
+            "suggest": {
+                "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+            },
+            "type": "library",
+            "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "GuzzleHttp\\Psr7\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "George Mponos",
+                    "email": "gmponos@gmail.com",
+                    "homepage": "https://github.com/gmponos"
+                },
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com",
+                    "homepage": "https://github.com/Nyholm"
+                },
+                {
+                    "name": "Márk Sági-Kazár",
+                    "email": "mark.sagikazar@gmail.com",
+                    "homepage": "https://github.com/sagikazarmark"
+                },
+                {
+                    "name": "Tobias Schultze",
+                    "email": "webmaster@tubo-world.de",
+                    "homepage": "https://github.com/Tobion"
+                },
+                {
+                    "name": "Márk Sági-Kazár",
+                    "email": "mark.sagikazar@gmail.com",
+                    "homepage": "https://sagikazarmark.hu"
+                }
+            ],
+            "description": "PSR-7 message implementation that also provides common utility methods",
+            "keywords": [
+                "http",
+                "message",
+                "psr-7",
+                "request",
+                "response",
+                "stream",
+                "uri",
+                "url"
+            ],
+            "support": {
+                "issues": "https://github.com/guzzle/psr7/issues",
+                "source": "https://github.com/guzzle/psr7/tree/2.13.0"
+            },
+            "time": "2026-07-16T22:23:49+00:00"
+        },
+        {
+            "name": "guzzlehttp/uri-template",
+            "version": "v1.0.10",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/uri-template/v1.0.10/guzzlehttp-uri-template-v1.0.10.zip",
+                "reference": "f6c24c21f42b990e9a58912b332d0874df6ba839",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2.5 || ^8.0",
+                "symfony/polyfill-php80": "^1.25"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.2",
+                "phpunit/phpunit": "^8.5.52 || ^9.6.34",
+                "uri-template/tests": "1.0.0"
+            },
+            "type": "library",
+            "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "GuzzleHttp\\UriTemplate\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "George Mponos",
+                    "email": "gmponos@gmail.com",
+                    "homepage": "https://github.com/gmponos"
+                },
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com",
+                    "homepage": "https://github.com/Nyholm"
+                }
+            ],
+            "description": "A polyfill class for uri_template of PHP",
+            "keywords": [
+                "guzzlehttp",
+                "uri-template"
+            ],
+            "support": {
+                "issues": "https://github.com/guzzle/uri-template/issues",
+                "source": "https://github.com/guzzle/uri-template/tree/v1.0.10"
+            },
+            "time": "2026-07-17T13:53:03+00:00"
+        },
+        {
+            "name": "illuminate/bus",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/bus/v12.64.0/illuminate-bus-v12.64.0.zip",
+                "reference": "9e70f409c744e0ba6b301fa608bb5b3c8c38669a",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/collections": "^12.0",
+                "illuminate/contracts": "^12.0",
+                "illuminate/pipeline": "^12.0",
+                "illuminate/support": "^12.0",
+                "php": "^8.2"
+            },
+            "suggest": {
+                "illuminate/queue": "Required to use closures when chaining jobs (^12.0)."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Illuminate\\Bus\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Bus package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2026-03-09T13:55:34+00:00"
+        },
+        {
+            "name": "illuminate/collections",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/collections/v12.64.0/illuminate-collections-v12.64.0.zip",
+                "reference": "83313b009c4afb6f02dbc090bdb67809756eefa2",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/conditionable": "^12.0",
+                "illuminate/contracts": "^12.0",
+                "illuminate/macroable": "^12.0",
+                "php": "^8.2",
+                "symfony/polyfill-php83": "^1.33",
+                "symfony/polyfill-php84": "^1.33",
+                "symfony/polyfill-php85": "^1.33"
+            },
+            "suggest": {
+                "illuminate/http": "Required to convert collections to API resources (^12.0).",
+                "symfony/var-dumper": "Required to use the dump method (^7.2)."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "functions.php",
+                    "helpers.php"
+                ],
+                "psr-4": {
+                    "Illuminate\\Support\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Collections package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2026-03-11T14:13:25+00:00"
+        },
+        {
+            "name": "illuminate/conditionable",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/conditionable/v12.64.0/illuminate-conditionable-v12.64.0.zip",
+                "reference": "ec677967c1f2faf90b8428919124d2184a4c9b49",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^8.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Illuminate\\Support\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Conditionable package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2025-05-13T15:08:45+00:00"
+        },
+        {
+            "name": "illuminate/container",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/container/v12.64.0/illuminate-container-v12.64.0.zip",
+                "reference": "9abe9dba6b3f5220205ce143069c975a601e4294",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/contracts": "^12.0",
+                "illuminate/reflection": "^12.0",
+                "php": "^8.2",
+                "psr/container": "^1.1.1|^2.0.1",
+                "symfony/polyfill-php84": "^1.33",
+                "symfony/polyfill-php85": "^1.33"
+            },
+            "provide": {
+                "psr/container-implementation": "1.1|2.0"
+            },
+            "suggest": {
+                "illuminate/auth": "Required to use the Auth attribute",
+                "illuminate/cache": "Required to use the Cache attribute",
+                "illuminate/config": "Required to use the Config attribute",
+                "illuminate/database": "Required to use the DB attribute",
+                "illuminate/filesystem": "Required to use the Storage attribute",
+                "illuminate/log": "Required to use the Log or Context attributes"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Illuminate\\Container\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Container package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2026-03-16T14:05:01+00:00"
+        },
+        {
+            "name": "illuminate/contracts",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/contracts/v12.64.0/illuminate-contracts-v12.64.0.zip",
+                "reference": "c16fd7ba7d8e6b8f336639ceb6b7e1ff6ed0efb5",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^8.2",
+                "psr/container": "^1.1.1|^2.0.1",
+                "psr/simple-cache": "^1.0|^2.0|^3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Illuminate\\Contracts\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Contracts package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2026-06-09T13:20:54+00:00"
+        },
+        {
+            "name": "illuminate/events",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/events/v12.64.0/illuminate-events-v12.64.0.zip",
+                "reference": "ff22aa6017bdbd90ace660f50638ed9c580ba555",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/bus": "^12.0",
+                "illuminate/collections": "^12.0",
+                "illuminate/container": "^12.0",
+                "illuminate/contracts": "^12.0",
+                "illuminate/macroable": "^12.0",
+                "illuminate/support": "^12.0",
+                "php": "^8.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "functions.php"
+                ],
+                "psr-4": {
+                    "Illuminate\\Events\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Events package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2026-03-05T16:20:14+00:00"
+        },
+        {
+            "name": "illuminate/filesystem",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/filesystem/v12.64.0/illuminate-filesystem-v12.64.0.zip",
+                "reference": "3b5ad9b385595d735689ebc2bfe701567cc4f1c3",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/collections": "^12.0",
+                "illuminate/contracts": "^12.0",
+                "illuminate/macroable": "^12.0",
+                "illuminate/support": "^12.0",
+                "php": "^8.2",
+                "symfony/finder": "^7.2.0"
+            },
+            "suggest": {
+                "ext-fileinfo": "Required to use the Filesystem class.",
+                "ext-ftp": "Required to use the Flysystem FTP driver.",
+                "ext-hash": "Required to use the Filesystem class.",
+                "illuminate/http": "Required for handling uploaded files (^12.0).",
+                "league/flysystem": "Required to use the Flysystem local driver (^3.25.1).",
+                "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).",
+                "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).",
+                "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).",
+                "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).",
+                "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).",
+                "symfony/mime": "Required to enable support for guessing extensions (^7.2)."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "functions.php"
+                ],
+                "psr-4": {
+                    "Illuminate\\Filesystem\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Filesystem package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2026-06-02T13:54:37+00:00"
+        },
+        {
+            "name": "illuminate/macroable",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/macroable/v12.64.0/illuminate-macroable-v12.64.0.zip",
+                "reference": "e295d62d89dcdb87e2b1bd70dd14d074a0ed73cc",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^8.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Illuminate\\Support\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Macroable package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2026-03-30T19:05:19+00:00"
+        },
+        {
+            "name": "illuminate/pipeline",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/pipeline/v12.64.0/illuminate-pipeline-v12.64.0.zip",
+                "reference": "b6a14c20d69a44bf0a6fba664a00d23ca71770ee",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/contracts": "^12.0",
+                "illuminate/macroable": "^12.0",
+                "illuminate/support": "^12.0",
+                "php": "^8.2"
+            },
+            "suggest": {
+                "illuminate/database": "Required to use database transactions (^12.0)."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Illuminate\\Pipeline\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Pipeline package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2025-08-20T13:36:50+00:00"
+        },
+        {
+            "name": "illuminate/redis",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/redis/v12.64.0/illuminate-redis-v12.64.0.zip",
+                "reference": "e46d4c3806d78d4d7733cd9b9bfb2fef30f4c8cb",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/collections": "^12.0",
+                "illuminate/contracts": "^12.0",
+                "illuminate/macroable": "^12.0",
+                "illuminate/support": "^12.0",
+                "php": "^8.2"
+            },
+            "suggest": {
+                "ext-redis": "Required to use the phpredis connector (^4.0|^5.0|^6.0).",
+                "predis/predis": "Required to use the predis connector (^2.3|^3.0)."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Illuminate\\Redis\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Redis package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2026-04-05T14:10:16+00:00"
+        },
+        {
+            "name": "illuminate/reflection",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/reflection/v12.64.0/illuminate-reflection-v12.64.0.zip",
+                "reference": "348cf5da9de89b596d7723be6425fb048e2bf4bb",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/collections": "^12.0",
+                "illuminate/contracts": "^12.0",
+                "php": "^8.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "helpers.php"
+                ],
+                "psr-4": {
+                    "Illuminate\\Support\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Reflection package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2026-02-25T15:25:18+00:00"
+        },
+        {
+            "name": "illuminate/support",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/support/v12.64.0/illuminate-support-v12.64.0.zip",
+                "reference": "bc7bc2db3e635697f81ea123511ae25b014a63fb",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/inflector": "^2.0",
+                "ext-ctype": "*",
+                "ext-filter": "*",
+                "ext-mbstring": "*",
+                "illuminate/collections": "^12.0",
+                "illuminate/conditionable": "^12.0",
+                "illuminate/contracts": "^12.0",
+                "illuminate/macroable": "^12.0",
+                "illuminate/reflection": "^12.0",
+                "nesbot/carbon": "^3.8.4",
+                "php": "^8.2",
+                "symfony/polyfill-php83": "^1.33",
+                "symfony/polyfill-php85": "^1.33",
+                "voku/portable-ascii": "^2.0.2"
+            },
+            "conflict": {
+                "tightenco/collect": "<5.5.33"
+            },
+            "replace": {
+                "spatie/once": "*"
+            },
+            "suggest": {
+                "illuminate/filesystem": "Required to use the Composer class (^12.0).",
+                "laravel/serializable-closure": "Required to use the once function (^1.3|^2.0).",
+                "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.7).",
+                "league/uri": "Required to use the Uri class (^7.5.1).",
+                "ramsey/uuid": "Required to use Str::uuid() (^4.7).",
+                "symfony/process": "Required to use the Composer class (^7.2).",
+                "symfony/uid": "Required to use Str::ulid() (^7.2).",
+                "symfony/var-dumper": "Required to use the dd function (^7.2).",
+                "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.6.1)."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "functions.php",
+                    "helpers.php"
+                ],
+                "psr-4": {
+                    "Illuminate\\Support\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Support package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2026-07-13T16:08:36+00:00"
+        },
+        {
+            "name": "illuminate/translation",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/translation/v12.64.0/illuminate-translation-v12.64.0.zip",
+                "reference": "4b555f3ca37523d1064d08e99774ab32fd0cc228",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/collections": "^12.0",
+                "illuminate/contracts": "^12.0",
+                "illuminate/filesystem": "^12.0",
+                "illuminate/macroable": "^12.0",
+                "illuminate/support": "^12.0",
+                "php": "^8.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Illuminate\\Translation\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Translation package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2026-03-18T14:19:27+00:00"
+        },
+        {
+            "name": "illuminate/validation",
+            "version": "v12.64.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/illuminate/validation/v12.64.0/illuminate-validation-v12.64.0.zip",
+                "reference": "297cff9c69885b1a9125ee4f26f77ef570abb2b6",
+                "shasum": ""
+            },
+            "require": {
+                "brick/math": "^0.11|^0.12|^0.13|^0.14",
+                "egulias/email-validator": "^3.2.5|^4.0",
+                "ext-filter": "*",
+                "ext-mbstring": "*",
+                "illuminate/collections": "^12.0",
+                "illuminate/container": "^12.0",
+                "illuminate/contracts": "^12.0",
+                "illuminate/macroable": "^12.0",
+                "illuminate/support": "^12.0",
+                "illuminate/translation": "^12.0",
+                "php": "^8.2",
+                "symfony/http-foundation": "^7.2",
+                "symfony/mime": "^7.2",
+                "symfony/polyfill-php83": "^1.33"
+            },
+            "suggest": {
+                "illuminate/database": "Required to use the database presence verifier (^12.0).",
+                "ramsey/uuid": "Required to use Validator::validateUuid() (^4.7)."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "12.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Illuminate\\Validation\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                }
+            ],
+            "description": "The Illuminate Validation package.",
+            "homepage": "https://laravel.com",
+            "support": {
+                "issues": "https://github.com/laravel/framework/issues",
+                "source": "https://github.com/laravel/framework"
+            },
+            "time": "2026-05-17T14:42:21+00:00"
+        },
+        {
+            "name": "jaeger/g-http",
+            "version": "V2.0.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/jaeger/g-http/V2.0.1/jaeger-g-http-V2.0.1.zip",
+                "reference": "29cb537c57f230980ca10622de190f04831e35e6",
+                "shasum": ""
+            },
+            "require": {
+                "guzzlehttp/guzzle": "^6.0 || ^7.0",
+                "php": ">=8.1",
+                "symfony/cache": "^6.4 || ^7.0"
+            },
+            "require-dev": {
+                "predis/predis": "^2.2"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Jaeger\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jaeger",
+                    "email": "JaegerCode@gmail.com"
+                }
+            ],
+            "description": "Simple Http client base on GuzzleHttp",
+            "support": {
+                "issues": "https://github.com/jae-jae/GHttp/issues",
+                "source": "https://github.com/jae-jae/GHttp/tree/V2.0.1"
+            },
+            "time": "2024-06-14T08:13:32+00:00"
+        },
+        {
+            "name": "jaeger/phpquery-single",
+            "version": "1.1.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/jaeger/phpquery-single/1.1.1/jaeger-phpquery-single-1.1.1.zip",
+                "reference": "39a650ade692a6b480c22220dce0c198d6a946fb",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "phpQuery.php"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Tobiasz Cudnik",
+                    "email": "tobiasz.cudnik@gmail.com",
+                    "homepage": "https://github.com/TobiaszCudnik",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Jaeger",
+                    "role": "Packager"
+                }
+            ],
+            "description": "phpQuery单文件版本,是Querylist的依赖(http://querylist.cc/),phpQuery项目主页:http://code.google.com/p/phpquery/",
+            "homepage": "http://code.google.com/p/phpquery/",
+            "support": {
+                "issues": "https://github.com/jae-jae/phpQuery-single/issues",
+                "source": "https://github.com/jae-jae/phpQuery-single/tree/1.1.1"
+            },
+            "time": "2022-03-26T15:01:16+00:00"
+        },
+        {
+            "name": "jaeger/querylist",
+            "version": "V4.4.7",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/jaeger/querylist/V4.4.7/jaeger-querylist-V4.4.7.zip",
+                "reference": "7888655eb12a0abea907954c4b6bbc817ecad3f1",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "jaeger/g-http": "^2.0",
+                "jaeger/phpquery-single": "^1",
+                "php": ">=8.1",
+                "symfony/var-dumper": ">3.4"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^8.5"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/Collect/Support/helpers.php",
+                    "src/Collect/Support/alias.php"
+                ],
+                "psr-4": {
+                    "QL\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jaeger",
+                    "email": "JaegerCode@gmail.com"
+                }
+            ],
+            "description": "Simple, elegant, extensible PHP Web Scraper (crawler/spider),Use the css3 dom selector,Based on phpQuery! 简洁、优雅、可扩展的PHP采集工具(爬虫),基于phpQuery。",
+            "homepage": "http://querylist.cc",
+            "keywords": [
+                "QueryList",
+                "phpQuery",
+                "spider"
+            ],
+            "support": {
+                "issues": "https://github.com/jae-jae/QueryList/issues",
+                "source": "https://github.com/jae-jae/QueryList/tree/V4.4.7"
+            },
+            "time": "2026-02-02T06:26:44+00:00"
+        },
+        {
+            "name": "laravel/serializable-closure",
+            "version": "v2.0.13",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/laravel/serializable-closure/v2.0.13/laravel-serializable-closure-v2.0.13.zip",
+                "reference": "b566ee0dd251f3c4078bed003a7ce015f5ea6dce",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^8.1"
+            },
+            "require-dev": {
+                "illuminate/support": "^10.0|^11.0|^12.0|^13.0",
+                "nesbot/carbon": "^2.67|^3.0",
+                "pestphp/pest": "^2.36|^3.0|^4.0",
+                "phpstan/phpstan": "^2.0",
+                "symfony/var-dumper": "^6.2.0|^7.0.0|^8.0.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Laravel\\SerializableClosure\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                },
+                {
+                    "name": "Nuno Maduro",
+                    "email": "nuno@laravel.com"
+                }
+            ],
+            "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.",
+            "keywords": [
+                "closure",
+                "laravel",
+                "serializable"
+            ],
+            "support": {
+                "issues": "https://github.com/laravel/serializable-closure/issues",
+                "source": "https://github.com/laravel/serializable-closure"
+            },
+            "time": "2026-04-16T14:03:50+00:00"
+        },
+        {
+            "name": "linfly/annotation",
+            "version": "2.1.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/linfly/annotation/2.1.0/linfly-annotation-2.1.0.zip",
+                "reference": "1ad9eeedf112f6cb0b2e61ff8c7e9244cdf62703",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^8.0",
+                "php-di/php-di": "^7.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "LinFly\\Annotation\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "description": "Webman plugin linfly/annotation",
+            "support": {
+                "issues": "https://github.com/imlinfly/webman-annotation/issues",
+                "source": "https://github.com/imlinfly/webman-annotation/tree/2.1.0"
+            },
+            "time": "2024-12-30T02:32:13+00:00"
+        },
+        {
+            "name": "maennchen/zipstream-php",
+            "version": "3.1.2",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/maennchen/zipstream-php/3.1.2/maennchen-zipstream-php-3.1.2.zip",
+                "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f",
+                "shasum": ""
+            },
+            "require": {
+                "ext-mbstring": "*",
+                "ext-zlib": "*",
+                "php-64bit": "^8.2"
+            },
+            "require-dev": {
+                "brianium/paratest": "^7.7",
+                "ext-zip": "*",
+                "friendsofphp/php-cs-fixer": "^3.16",
+                "guzzlehttp/guzzle": "^7.5",
+                "mikey179/vfsstream": "^1.6",
+                "php-coveralls/php-coveralls": "^2.5",
+                "phpunit/phpunit": "^11.0",
+                "vimeo/psalm": "^6.0"
+            },
+            "suggest": {
+                "guzzlehttp/psr7": "^2.4",
+                "psr/http-message": "^2.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "ZipStream\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Paul Duncan",
+                    "email": "pabs@pablotron.org"
+                },
+                {
+                    "name": "Jonatan Männchen",
+                    "email": "jonatan@maennchen.ch"
+                },
+                {
+                    "name": "Jesse Donat",
+                    "email": "donatj@gmail.com"
+                },
+                {
+                    "name": "András Kolesár",
+                    "email": "kolesar@kolesar.hu"
+                }
+            ],
+            "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
+            "keywords": [
+                "stream",
+                "zip"
+            ],
+            "support": {
+                "issues": "https://github.com/maennchen/ZipStream-PHP/issues",
+                "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2"
+            },
+            "time": "2025-01-27T12:07:53+00:00"
+        },
+        {
+            "name": "markbaker/complex",
+            "version": "3.0.2",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/markbaker/complex/3.0.2/markbaker-complex-3.0.2.zip",
+                "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2 || ^8.0"
+            },
+            "require-dev": {
+                "dealerdirect/phpcodesniffer-composer-installer": "dev-master",
+                "phpcompatibility/php-compatibility": "^9.3",
+                "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
+                "squizlabs/php_codesniffer": "^3.7"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Complex\\": "classes/src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mark Baker",
+                    "email": "mark@lange.demon.co.uk"
+                }
+            ],
+            "description": "PHP Class for working with complex numbers",
+            "homepage": "https://github.com/MarkBaker/PHPComplex",
+            "keywords": [
+                "complex",
+                "mathematics"
+            ],
+            "support": {
+                "issues": "https://github.com/MarkBaker/PHPComplex/issues",
+                "source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2"
+            },
+            "time": "2022-12-06T16:21:08+00:00"
+        },
+        {
+            "name": "markbaker/matrix",
+            "version": "3.0.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/markbaker/matrix/3.0.1/markbaker-matrix-3.0.1.zip",
+                "reference": "728434227fe21be27ff6d86621a1b13107a2562c",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1 || ^8.0"
+            },
+            "require-dev": {
+                "dealerdirect/phpcodesniffer-composer-installer": "dev-master",
+                "phpcompatibility/php-compatibility": "^9.3",
+                "phpdocumentor/phpdocumentor": "2.*",
+                "phploc/phploc": "^4.0",
+                "phpmd/phpmd": "2.*",
+                "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
+                "sebastian/phpcpd": "^4.0",
+                "squizlabs/php_codesniffer": "^3.7"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Matrix\\": "classes/src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mark Baker",
+                    "email": "mark@demon-angel.eu"
+                }
+            ],
+            "description": "PHP Class for working with matrices",
+            "homepage": "https://github.com/MarkBaker/PHPMatrix",
+            "keywords": [
+                "mathematics",
+                "matrix",
+                "vector"
+            ],
+            "support": {
+                "issues": "https://github.com/MarkBaker/PHPMatrix/issues",
+                "source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1"
+            },
+            "time": "2022-12-02T22:17:43+00:00"
+        },
+        {
+            "name": "monolog/monolog",
+            "version": "2.11.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/monolog/monolog/2.11.0/monolog-monolog-2.11.0.zip",
+                "reference": "37308608e599f34a1a4845b16440047ec98a172a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2",
+                "psr/log": "^1.0.1 || ^2.0 || ^3.0"
+            },
+            "provide": {
+                "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0"
+            },
+            "require-dev": {
+                "aws/aws-sdk-php": "^2.4.9 || ^3.0",
+                "doctrine/couchdb": "~1.0@dev",
+                "elasticsearch/elasticsearch": "^7 || ^8",
+                "ext-json": "*",
+                "graylog2/gelf-php": "^1.4.2 || ^2@dev",
+                "guzzlehttp/guzzle": "^7.4",
+                "guzzlehttp/psr7": "^2.2",
+                "mongodb/mongodb": "^1.8 || ^2.0",
+                "php-amqplib/php-amqplib": "~2.4 || ^3",
+                "phpspec/prophecy": "^1.15",
+                "phpstan/phpstan": "^1.10",
+                "phpunit/phpunit": "^8.5.38 || ^9.6.19",
+                "predis/predis": "^1.1 || ^2.0",
+                "rollbar/rollbar": "^1.3 || ^2 || ^3",
+                "ruflin/elastica": "^7",
+                "swiftmailer/swiftmailer": "^5.3|^6.0",
+                "symfony/mailer": "^5.4 || ^6",
+                "symfony/mime": "^5.4 || ^6"
+            },
+            "suggest": {
+                "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+                "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+                "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
+                "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+                "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
+                "ext-mbstring": "Allow to work properly with unicode symbols",
+                "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
+                "ext-openssl": "Required to send log messages using SSL",
+                "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
+                "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+                "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
+                "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
+                "rollbar/rollbar": "Allow sending log messages to Rollbar",
+                "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-main": "2.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Monolog\\": "src/Monolog"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jordi Boggiano",
+                    "email": "j.boggiano@seld.be",
+                    "homepage": "https://seld.be"
+                }
+            ],
+            "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+            "homepage": "https://github.com/Seldaek/monolog",
+            "keywords": [
+                "log",
+                "logging",
+                "psr-3"
+            ],
+            "support": {
+                "issues": "https://github.com/Seldaek/monolog/issues",
+                "source": "https://github.com/Seldaek/monolog/tree/2.11.0"
+            },
+            "time": "2026-01-01T13:05:00+00:00"
+        },
+        {
+            "name": "nesbot/carbon",
+            "version": "3.13.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/nesbot/carbon/3.13.1/nesbot-carbon-3.13.1.zip",
+                "reference": "2937ad3d1d2c506fd2bc97d571438a95641f44e2",
+                "shasum": ""
+            },
+            "require": {
+                "carbonphp/carbon-doctrine-types": "<100.0",
+                "ext-json": "*",
+                "php": "^8.1",
+                "psr/clock": "^1.0",
+                "symfony/clock": "^6.3.12 || ^7.0 || ^8.0",
+                "symfony/polyfill-mbstring": "^1.0",
+                "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0 || ^8.0"
+            },
+            "provide": {
+                "psr/clock-implementation": "1.0"
+            },
+            "require-dev": {
+                "doctrine/dbal": "^3.6.3 || ^4.0",
+                "doctrine/orm": "^2.15.2 || ^3.0",
+                "friendsofphp/php-cs-fixer": "^v3.87.1",
+                "kylekatarnls/multi-tester": "^2.5.3",
+                "phpmd/phpmd": "^2.15.0",
+                "phpstan/extension-installer": "^1.4.3",
+                "phpstan/phpstan": "^2.1.22",
+                "phpunit/phpunit": "^10.5.53",
+                "squizlabs/php_codesniffer": "^3.13.4 || ^4.0.0"
+            },
+            "bin": [
+                "bin/carbon"
+            ],
+            "type": "library",
+            "extra": {
+                "laravel": {
+                    "providers": [
+                        "Carbon\\Laravel\\ServiceProvider"
+                    ]
+                },
+                "phpstan": {
+                    "includes": [
+                        "extension.neon"
+                    ]
+                },
+                "branch-alias": {
+                    "dev-2.x": "2.x-dev",
+                    "dev-master": "3.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Carbon\\": "src/Carbon/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Brian Nesbitt",
+                    "email": "brian@nesbot.com",
+                    "homepage": "https://markido.com"
+                },
+                {
+                    "name": "kylekatarnls",
+                    "homepage": "https://github.com/kylekatarnls"
+                }
+            ],
+            "description": "An API extension for DateTime that supports 281 different languages.",
+            "homepage": "https://carbonphp.github.io/carbon/",
+            "keywords": [
+                "date",
+                "datetime",
+                "time"
+            ],
+            "support": {
+                "docs": "https://carbonphp.github.io/carbon/guide/getting-started/introduction.html",
+                "issues": "https://github.com/CarbonPHP/carbon/issues",
+                "source": "https://github.com/CarbonPHP/carbon"
+            },
+            "time": "2026-07-09T18:23:49+00:00"
+        },
+        {
+            "name": "nikic/fast-route",
+            "version": "1.3.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/nikic/fast-route/1.3.1/nikic-fast-route-1.3.1.zip",
+                "reference": "7476684f39bb9124b3be69ed3d84b66723920298",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.4.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8.35|~5.7"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/functions.php"
+                ],
+                "psr-4": {
+                    "FastRoute\\": "src/"
+                }
+            },
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Nikita Popov",
+                    "email": "nikic@php.net"
+                }
+            ],
+            "description": "Fast request router for PHP",
+            "keywords": [
+                "router",
+                "routing"
+            ],
+            "support": {
+                "issues": "https://github.com/nikic/FastRoute/issues",
+                "source": "https://github.com/nikic/FastRoute/tree/1.3.1"
+            },
+            "time": "2026-07-09T19:38:47+00:00"
+        },
+        {
+            "name": "overtrue/pinyin",
+            "version": "6.0.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/overtrue/pinyin/6.0.1/overtrue-pinyin-6.0.1.zip",
+                "reference": "d79364f289f5ccdabdd3142556d4254c7574f87c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.1"
+            },
+            "require-dev": {
+                "brainmaestro/composer-git-hooks": "^3.0",
+                "laravel/pint": "^1.10",
+                "nunomaduro/termwind": "^1.0 || ^2.0",
+                "phpunit/phpunit": "^10.5 || ^11.5 || ^12.0"
+            },
+            "bin": [
+                "bin/pinyin"
+            ],
+            "type": "library",
+            "extra": {
+                "hooks": {
+                    "pre-push": [
+                        "composer pint",
+                        "composer test"
+                    ],
+                    "pre-commit": [
+                        "composer pint",
+                        "composer test"
+                    ]
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Overtrue\\Pinyin\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "overtrue",
+                    "email": "anzhengchao@gmail.com",
+                    "homepage": "http://github.com/overtrue"
+                }
+            ],
+            "description": "Chinese to pinyin translator.",
+            "homepage": "https://github.com/overtrue/pinyin",
+            "keywords": [
+                "Chinese",
+                "Pinyin",
+                "cn2pinyin"
+            ],
+            "support": {
+                "issues": "https://github.com/overtrue/pinyin/issues",
+                "source": "https://github.com/overtrue/pinyin/tree/6.0.1"
+            },
+            "time": "2026-03-06T13:15:43+00:00"
+        },
+        {
+            "name": "php-di/invoker",
+            "version": "2.3.7",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/php-di/invoker/2.3.7/php-di-invoker-2.3.7.zip",
+                "reference": "3c1ddfdef181431fbc4be83378f6d036d59e81e1",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.3",
+                "psr/container": "^1.0|^2.0"
+            },
+            "require-dev": {
+                "athletic/athletic": "~0.1.8",
+                "mnapoli/hard-mode": "~0.3.0",
+                "phpunit/phpunit": "^9.0 || ^10 || ^11 || ^12"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Invoker\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "description": "Generic and extensible callable invoker",
+            "homepage": "https://github.com/PHP-DI/Invoker",
+            "keywords": [
+                "callable",
+                "dependency",
+                "dependency-injection",
+                "injection",
+                "invoke",
+                "invoker"
+            ],
+            "support": {
+                "issues": "https://github.com/PHP-DI/Invoker/issues",
+                "source": "https://github.com/PHP-DI/Invoker/tree/2.3.7"
+            },
+            "time": "2025-08-30T10:22:22+00:00"
+        },
+        {
+            "name": "php-di/php-di",
+            "version": "7.1.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/php-di/php-di/7.1.1/php-di-php-di-7.1.1.zip",
+                "reference": "f88054cc052e40dbe7b383c8817c19442d480352",
+                "shasum": ""
+            },
+            "require": {
+                "laravel/serializable-closure": "^1.0 || ^2.0",
+                "php": ">=8.0",
+                "php-di/invoker": "^2.0",
+                "psr/container": "^1.1 || ^2.0"
+            },
+            "provide": {
+                "psr/container-implementation": "^1.0"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "^3",
+                "friendsofphp/proxy-manager-lts": "^1",
+                "mnapoli/phpunit-easymock": "^1.3",
+                "phpunit/phpunit": "^9.6 || ^10 || ^11",
+                "vimeo/psalm": "^5|^6"
+            },
+            "suggest": {
+                "friendsofphp/proxy-manager-lts": "Install it if you want to use lazy injection (version ^1)"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/functions.php"
+                ],
+                "psr-4": {
+                    "DI\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "description": "The dependency injection container for humans",
+            "homepage": "https://php-di.org/",
+            "keywords": [
+                "PSR-11",
+                "container",
+                "container-interop",
+                "dependency injection",
+                "di",
+                "ioc",
+                "psr11"
+            ],
+            "support": {
+                "issues": "https://github.com/PHP-DI/PHP-DI/issues",
+                "source": "https://github.com/PHP-DI/PHP-DI/tree/7.1.1"
+            },
+            "time": "2025-08-16T11:10:48+00:00"
+        },
+        {
+            "name": "phpoffice/phpspreadsheet",
+            "version": "5.9.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/phpoffice/phpspreadsheet/5.9.0/phpoffice-phpspreadsheet-5.9.0.zip",
+                "reference": "05e99ebf61238a70227b4d9cc02d0030d34f6339",
+                "shasum": ""
+            },
+            "require": {
+                "composer/pcre": "^1||^2||^3",
+                "ext-ctype": "*",
+                "ext-dom": "*",
+                "ext-fileinfo": "*",
+                "ext-filter": "*",
+                "ext-gd": "*",
+                "ext-iconv": "*",
+                "ext-libxml": "*",
+                "ext-mbstring": "*",
+                "ext-simplexml": "*",
+                "ext-xml": "*",
+                "ext-xmlreader": "*",
+                "ext-xmlwriter": "*",
+                "ext-zip": "*",
+                "ext-zlib": "*",
+                "maennchen/zipstream-php": "^2.1 || ^3.0",
+                "markbaker/complex": "^3.0",
+                "markbaker/matrix": "^3.0",
+                "php": "^8.2",
+                "psr/simple-cache": "^1.0 || ^2.0 || ^3.0"
+            },
+            "require-dev": {
+                "dealerdirect/phpcodesniffer-composer-installer": "dev-main",
+                "dompdf/dompdf": "^2.0 || ^3.0",
+                "ext-intl": "*",
+                "friendsofphp/php-cs-fixer": "^3.2",
+                "mitoteam/jpgraph": "^10.5",
+                "mpdf/mpdf": "^8.1.1",
+                "phpcompatibility/php-compatibility": "^9.3",
+                "phpstan/phpstan": "^1.1 || ^2.0",
+                "phpstan/phpstan-deprecation-rules": "^1.0 || ^2.0",
+                "phpstan/phpstan-phpunit": "^1.0 || ^2.0",
+                "phpunit/phpunit": "^10.5 || ^11.0",
+                "squizlabs/php_codesniffer": "^3.7",
+                "tecnickcom/tcpdf": "^6.5"
+            },
+            "suggest": {
+                "dompdf/dompdf": "Option for rendering PDF with PDF Writer",
+                "ext-intl": "PHP Internationalization Functions, required for NumberFormat Wizard and StringHelper::setLocale()",
+                "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
+                "mpdf/mpdf": "Option for rendering PDF with PDF Writer",
+                "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Maarten Balliauw",
+                    "homepage": "https://blog.maartenballiauw.be"
+                },
+                {
+                    "name": "Mark Baker",
+                    "homepage": "https://markbakeruk.net"
+                },
+                {
+                    "name": "Franck Lefevre",
+                    "homepage": "https://rootslabs.net"
+                },
+                {
+                    "name": "Erik Tilt"
+                },
+                {
+                    "name": "Adrien Crivelli"
+                },
+                {
+                    "name": "Owen Leibman"
+                }
+            ],
+            "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
+            "homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
+            "keywords": [
+                "OpenXML",
+                "excel",
+                "gnumeric",
+                "ods",
+                "php",
+                "spreadsheet",
+                "xls",
+                "xlsx"
+            ],
+            "support": {
+                "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
+                "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/5.9.0"
+            },
+            "time": "2026-07-12T19:17:39+00:00"
+        },
+        {
+            "name": "phpoption/phpoption",
+            "version": "1.9.5",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/phpoption/phpoption/1.9.5/phpoption-phpoption-1.9.5.zip",
+                "reference": "75365b91986c2405cf5e1e012c5595cd487a98be",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2.5 || ^8.0"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.2",
+                "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34"
+            },
+            "type": "library",
+            "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                },
+                "branch-alias": {
+                    "dev-master": "1.9-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "PhpOption\\": "src/PhpOption/"
+                }
+            },
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Johannes M. Schmitt",
+                    "email": "schmittjoh@gmail.com",
+                    "homepage": "https://github.com/schmittjoh"
+                },
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                }
+            ],
+            "description": "Option Type for PHP",
+            "keywords": [
+                "language",
+                "option",
+                "php",
+                "type"
+            ],
+            "support": {
+                "issues": "https://github.com/schmittjoh/php-option/issues",
+                "source": "https://github.com/schmittjoh/php-option/tree/1.9.5"
+            },
+            "time": "2025-12-27T19:41:33+00:00"
+        },
+        {
+            "name": "psr/cache",
+            "version": "3.0.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/cache/3.0.0/psr-cache-3.0.0.zip",
+                "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.0.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Cache\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for caching libraries",
+            "keywords": [
+                "cache",
+                "psr",
+                "psr-6"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/cache/tree/3.0.0"
+            },
+            "time": "2021-02-03T23:26:27+00:00"
+        },
+        {
+            "name": "psr/clock",
+            "version": "1.0.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/clock/1.0.0/psr-clock-1.0.0.zip",
+                "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0 || ^8.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Clock\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for reading the clock.",
+            "homepage": "https://github.com/php-fig/clock",
+            "keywords": [
+                "clock",
+                "now",
+                "psr",
+                "psr-20",
+                "time"
+            ],
+            "support": {
+                "issues": "https://github.com/php-fig/clock/issues",
+                "source": "https://github.com/php-fig/clock/tree/1.0.0"
+            },
+            "time": "2022-11-25T14:36:26+00:00"
+        },
+        {
+            "name": "psr/container",
+            "version": "2.0.2",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/container/2.0.2/psr-container-2.0.2.zip",
+                "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.4.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Container\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common Container Interface (PHP FIG PSR-11)",
+            "homepage": "https://github.com/php-fig/container",
+            "keywords": [
+                "PSR-11",
+                "container",
+                "container-interface",
+                "container-interop",
+                "psr"
+            ],
+            "support": {
+                "issues": "https://github.com/php-fig/container/issues",
+                "source": "https://github.com/php-fig/container/tree/2.0.2"
+            },
+            "time": "2021-11-05T16:47:00+00:00"
+        },
+        {
+            "name": "psr/http-client",
+            "version": "1.0.3",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/http-client/1.0.3/psr-http-client-1.0.3.zip",
+                "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0 || ^8.0",
+                "psr/http-message": "^1.0 || ^2.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Http\\Client\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for HTTP clients",
+            "homepage": "https://github.com/php-fig/http-client",
+            "keywords": [
+                "http",
+                "http-client",
+                "psr",
+                "psr-18"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/http-client"
+            },
+            "time": "2023-09-23T14:17:50+00:00"
+        },
+        {
+            "name": "psr/http-factory",
+            "version": "1.1.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/http-factory/1.1.0/psr-http-factory-1.1.0.zip",
+                "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1",
+                "psr/http-message": "^1.0 || ^2.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Http\\Message\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
+            "keywords": [
+                "factory",
+                "http",
+                "message",
+                "psr",
+                "psr-17",
+                "psr-7",
+                "request",
+                "response"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/http-factory"
+            },
+            "time": "2024-04-15T12:06:14+00:00"
+        },
+        {
+            "name": "psr/http-message",
+            "version": "2.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/http-message/2.0/psr-http-message-2.0.zip",
+                "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2 || ^8.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Http\\Message\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for HTTP messages",
+            "homepage": "https://github.com/php-fig/http-message",
+            "keywords": [
+                "http",
+                "http-message",
+                "psr",
+                "psr-7",
+                "request",
+                "response"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/http-message/tree/2.0"
+            },
+            "time": "2023-04-04T09:54:51+00:00"
+        },
+        {
+            "name": "psr/log",
+            "version": "3.0.2",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/log/3.0.2/psr-log-3.0.2.zip",
+                "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.0.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Log\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for logging libraries",
+            "homepage": "https://github.com/php-fig/log",
+            "keywords": [
+                "log",
+                "psr",
+                "psr-3"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/log/tree/3.0.2"
+            },
+            "time": "2024-09-11T13:17:53+00:00"
+        },
+        {
+            "name": "psr/simple-cache",
+            "version": "3.0.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/simple-cache/3.0.0/psr-simple-cache-3.0.0.zip",
+                "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.0.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\SimpleCache\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interfaces for simple caching",
+            "keywords": [
+                "cache",
+                "caching",
+                "psr",
+                "psr-16",
+                "simple-cache"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
+            },
+            "time": "2021-10-29T13:26:27+00:00"
+        },
+        {
+            "name": "qcloud/cos-sdk-v5",
+            "version": "v2.6.16",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/qcloud/cos-sdk-v5/v2.6.16/qcloud-cos-sdk-v5-v2.6.16.zip",
+                "reference": "22366f4b4f7f277e67aa72eea8d1e02a5f9943e2",
+                "shasum": ""
+            },
+            "require": {
+                "ext-curl": "*",
+                "ext-json": "*",
+                "ext-libxml": "*",
+                "ext-mbstring": "*",
+                "ext-simplexml": "*",
+                "guzzlehttp/guzzle": "^6.2.1 || ^7.0",
+                "guzzlehttp/guzzle-services": "^1.1",
+                "guzzlehttp/psr7": "^1.3.1 || ^2.0",
+                "php": ">=5.6"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.4-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "src/Common.php"
+                ],
+                "psr-4": {
+                    "Qcloud\\Cos\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "yaozongyou",
+                    "email": "yaozongyou@vip.qq.com"
+                },
+                {
+                    "name": "lewzylu",
+                    "email": "327874225@qq.com"
+                },
+                {
+                    "name": "tuunalai",
+                    "email": "550566181@qq.com"
+                }
+            ],
+            "description": "PHP SDK for QCloud COS",
+            "keywords": [
+                "cos",
+                "php",
+                "qcloud"
+            ],
+            "support": {
+                "issues": "https://github.com/tencentyun/cos-php-sdk-v5/issues",
+                "source": "https://github.com/tencentyun/cos-php-sdk-v5/tree/v2.6.16"
+            },
+            "time": "2025-01-21T12:49:21+00:00"
+        },
+        {
+            "name": "ralouphie/getallheaders",
+            "version": "3.0.3",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/ralouphie/getallheaders/3.0.3/ralouphie-getallheaders-3.0.3.zip",
+                "reference": "120b605dfeb996808c31b6477290a714d356e822",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6"
+            },
+            "require-dev": {
+                "php-coveralls/php-coveralls": "^2.1",
+                "phpunit/phpunit": "^5 || ^6.5"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/getallheaders.php"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Ralph Khattar",
+                    "email": "ralph.khattar@gmail.com"
+                }
+            ],
+            "description": "A polyfill for getallheaders.",
+            "support": {
+                "issues": "https://github.com/ralouphie/getallheaders/issues",
+                "source": "https://github.com/ralouphie/getallheaders/tree/develop"
+            },
+            "time": "2019-03-08T08:55:37+00:00"
+        },
+        {
+            "name": "shopwwi/webman-auth",
+            "version": "v2.0.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/shopwwi/webman-auth/v2.0.1/shopwwi-webman-auth-v2.0.1.zip",
+                "reference": "76afe0eb98100d6051284f6b3bc9531d5f04a3dd",
+                "shasum": ""
+            },
+            "require": {
+                "firebase/php-jwt": ">=5.4|^6.0",
+                "php": ">=7.2",
+                "webman/console": "^1.0 || ^2.0 || dev-master"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Shopwwi\\WebmanAuth\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Tycoon Song",
+                    "email": "8988354@qq.com"
+                }
+            ],
+            "description": "webman auth",
+            "keywords": [
+                "auth",
+                "webman"
+            ],
+            "support": {
+                "issues": "https://github.com/shopwwi/webman-auth/issues",
+                "source": "https://github.com/shopwwi/webman-auth/tree/v2.0.1"
+            },
+            "time": "2026-05-26T07:51:05+00:00"
+        },
+        {
+            "name": "symfony/cache",
+            "version": "v7.3.11",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/cache/v7.3.11/symfony-cache-v7.3.11.zip",
+                "reference": "e3e76b9ba0dff3dfe08ebda500723976dd9de407",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.2",
+                "psr/cache": "^2.0|^3.0",
+                "psr/log": "^1.1|^2|^3",
+                "symfony/cache-contracts": "^3.6",
+                "symfony/deprecation-contracts": "^2.5|^3.0",
+                "symfony/service-contracts": "^2.5|^3",
+                "symfony/var-exporter": "^6.4|^7.0"
+            },
+            "conflict": {
+                "doctrine/dbal": "<3.6",
+                "symfony/dependency-injection": "<6.4",
+                "symfony/http-kernel": "<6.4",
+                "symfony/var-dumper": "<6.4"
+            },
+            "provide": {
+                "psr/cache-implementation": "2.0|3.0",
+                "psr/simple-cache-implementation": "1.0|2.0|3.0",
+                "symfony/cache-implementation": "1.1|2.0|3.0"
+            },
+            "require-dev": {
+                "cache/integration-tests": "dev-master",
+                "doctrine/dbal": "^3.6|^4",
+                "predis/predis": "^1.1|^2.0",
+                "psr/simple-cache": "^1.0|^2.0|^3.0",
+                "symfony/clock": "^6.4|^7.0",
+                "symfony/config": "^6.4|^7.0",
+                "symfony/dependency-injection": "^6.4|^7.0",
+                "symfony/filesystem": "^6.4|^7.0",
+                "symfony/http-kernel": "^6.4|^7.0",
+                "symfony/messenger": "^6.4|^7.0",
+                "symfony/var-dumper": "^6.4|^7.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Cache\\": ""
+                },
+                "classmap": [
+                    "Traits/ValueWrapper.php"
+                ],
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Provides extended PSR-6, PSR-16 (and tags) implementations",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "caching",
+                "psr6"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/cache/tree/v7.3.11"
+            },
+            "time": "2026-01-27T16:12:03+00:00"
+        },
+        {
+            "name": "symfony/cache-contracts",
+            "version": "v3.7.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/cache-contracts/v3.7.1/symfony-cache-contracts-v3.7.1.zip",
+                "reference": "9789738bc19af1106dc54d6afba9a0b467516cf2",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.1",
+                "psr/cache": "^3.0"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/contracts",
+                    "name": "symfony/contracts"
+                },
+                "branch-alias": {
+                    "dev-main": "3.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Contracts\\Cache\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Generic abstractions related to caching",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "abstractions",
+                "contracts",
+                "decoupling",
+                "interfaces",
+                "interoperability",
+                "standards"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/cache-contracts/tree/v3.7.1"
+            },
+            "time": "2026-06-05T06:23:12+00:00"
+        },
+        {
+            "name": "symfony/clock",
+            "version": "v7.4.8",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/clock/v7.4.8/symfony-clock-v7.4.8.zip",
+                "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.2",
+                "psr/clock": "^1.0",
+                "symfony/polyfill-php83": "^1.28"
+            },
+            "provide": {
+                "psr/clock-implementation": "1.0"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "Resources/now.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Component\\Clock\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Decouples applications from the system clock",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "clock",
+                "psr20",
+                "time"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/clock/tree/v7.4.8"
+            },
+            "time": "2026-03-24T13:12:05+00:00"
+        },
+        {
+            "name": "symfony/console",
+            "version": "v7.4.14",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/console/v7.4.14/symfony-console-v7.4.14.zip",
+                "reference": "92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.2",
+                "symfony/deprecation-contracts": "^2.5|^3",
+                "symfony/polyfill-mbstring": "~1.0",
+                "symfony/service-contracts": "^2.5|^3",
+                "symfony/string": "^7.2|^8.0"
+            },
+            "conflict": {
+                "symfony/dependency-injection": "<6.4",
+                "symfony/dotenv": "<6.4",
+                "symfony/event-dispatcher": "<6.4",
+                "symfony/lock": "<6.4",
+                "symfony/process": "<6.4"
+            },
+            "provide": {
+                "psr/log-implementation": "1.0|2.0|3.0"
+            },
+            "require-dev": {
+                "psr/log": "^1|^2|^3",
+                "symfony/config": "^6.4|^7.0|^8.0",
+                "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+                "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
+                "symfony/http-foundation": "^6.4|^7.0|^8.0",
+                "symfony/http-kernel": "^6.4|^7.0|^8.0",
+                "symfony/lock": "^6.4|^7.0|^8.0",
+                "symfony/messenger": "^6.4|^7.0|^8.0",
+                "symfony/process": "^6.4|^7.0|^8.0",
+                "symfony/stopwatch": "^6.4|^7.0|^8.0",
+                "symfony/var-dumper": "^6.4|^7.0|^8.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Console\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Eases the creation of beautiful and testable command line interfaces",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "cli",
+                "command-line",
+                "console",
+                "terminal"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/console/tree/v7.4.14"
+            },
+            "time": "2026-06-16T11:50:14+00:00"
+        },
+        {
+            "name": "symfony/deprecation-contracts",
+            "version": "v3.7.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/deprecation-contracts/v3.7.1/symfony-deprecation-contracts-v3.7.1.zip",
+                "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.1"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/contracts",
+                    "name": "symfony/contracts"
+                },
+                "branch-alias": {
+                    "dev-main": "3.7-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "function.php"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "A generic function and convention to trigger deprecation notices",
+            "homepage": "https://symfony.com",
+            "support": {
+                "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1"
+            },
+            "time": "2026-06-05T06:23:12+00:00"
+        },
+        {
+            "name": "symfony/finder",
+            "version": "v7.4.14",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/finder/v7.4.14/symfony-finder-v7.4.14.zip",
+                "reference": "13b38720174286f55d1761152b575a8d1436fc25",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.2"
+            },
+            "require-dev": {
+                "symfony/filesystem": "^6.4|^7.0|^8.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Finder\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Finds files and directories via an intuitive fluent interface",
+            "homepage": "https://symfony.com",
+            "support": {
+                "source": "https://github.com/symfony/finder/tree/v7.4.14"
+            },
+            "time": "2026-06-27T08:31:18+00:00"
+        },
+        {
+            "name": "symfony/http-foundation",
+            "version": "v7.4.14",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/http-foundation/v7.4.14/symfony-http-foundation-v7.4.14.zip",
+                "reference": "06db5ae1552177bf8572f8908839f12e3c06aed3",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.2",
+                "symfony/deprecation-contracts": "^2.5|^3",
+                "symfony/polyfill-mbstring": "^1.1"
+            },
+            "conflict": {
+                "doctrine/dbal": "<3.6",
+                "symfony/cache": "<6.4.12|>=7.0,<7.1.5"
+            },
+            "require-dev": {
+                "doctrine/dbal": "^3.6|^4",
+                "predis/predis": "^1.1|^2.0",
+                "symfony/cache": "^6.4.12|^7.1.5|^8.0",
+                "symfony/clock": "^6.4|^7.0|^8.0",
+                "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+                "symfony/expression-language": "^6.4|^7.0|^8.0",
+                "symfony/http-kernel": "^6.4|^7.0|^8.0",
+                "symfony/mime": "^6.4|^7.0|^8.0",
+                "symfony/rate-limiter": "^6.4|^7.0|^8.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\HttpFoundation\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Defines an object-oriented layer for the HTTP specification",
+            "homepage": "https://symfony.com",
+            "support": {
+                "source": "https://github.com/symfony/http-foundation/tree/v7.4.14"
+            },
+            "time": "2026-06-11T07:31:44+00:00"
+        },
+        {
+            "name": "symfony/mime",
+            "version": "v7.4.13",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/mime/v7.4.13/symfony-mime-v7.4.13.zip",
+                "reference": "a845722765c4f6b2ce88beaf4f4479975b186770",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.2",
+                "symfony/deprecation-contracts": "^2.5|^3",
+                "symfony/polyfill-intl-idn": "^1.10",
+                "symfony/polyfill-mbstring": "^1.0"
+            },
+            "conflict": {
+                "egulias/email-validator": "~3.0.0",
+                "phpdocumentor/reflection-docblock": "<5.2|>=7",
+                "phpdocumentor/type-resolver": "<1.5.1",
+                "symfony/mailer": "<6.4",
+                "symfony/serializer": "<6.4.3|>7.0,<7.0.3"
+            },
+            "require-dev": {
+                "egulias/email-validator": "^2.1.10|^3.1|^4",
+                "league/html-to-markdown": "^5.0",
+                "phpdocumentor/reflection-docblock": "^5.2|^6.0",
+                "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+                "symfony/process": "^6.4|^7.0|^8.0",
+                "symfony/property-access": "^6.4|^7.0|^8.0",
+                "symfony/property-info": "^6.4|^7.0|^8.0",
+                "symfony/serializer": "^6.4.3|^7.0.3|^8.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Mime\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Allows manipulating MIME messages",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "mime",
+                "mime-type"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/mime/tree/v7.4.13"
+            },
+            "time": "2026-05-23T16:22:37+00:00"
+        },
+        {
+            "name": "symfony/polyfill-ctype",
+            "version": "v1.37.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-ctype/v1.37.0/symfony-polyfill-ctype-v1.37.0.zip",
+                "reference": "141046a8f9477948ff284fa65be2095baafb94f2",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "provide": {
+                "ext-ctype": "*"
+            },
+            "suggest": {
+                "ext-ctype": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Ctype\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Gert de Pagter",
+                    "email": "BackEndTea@gmail.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for ctype functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "ctype",
+                "polyfill",
+                "portable"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0"
+            },
+            "time": "2026-04-10T16:19:22+00:00"
+        },
+        {
+            "name": "symfony/polyfill-intl-grapheme",
+            "version": "v1.38.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-intl-grapheme/v1.38.1/symfony-polyfill-intl-grapheme-v1.38.1.zip",
+                "reference": "e9247d281d694a5120554d9afaf54e070e88a603",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "suggest": {
+                "ext-intl": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for intl's grapheme_* functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "grapheme",
+                "intl",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.38.1"
+            },
+            "time": "2026-05-26T05:58:03+00:00"
+        },
+        {
+            "name": "symfony/polyfill-intl-idn",
+            "version": "v1.38.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-intl-idn/v1.38.1/symfony-polyfill-intl-idn-v1.38.1.zip",
+                "reference": "dc21118016c039a66235cf93d96b435ffb282412",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2",
+                "symfony/polyfill-intl-normalizer": "^1.10"
+            },
+            "suggest": {
+                "ext-intl": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Intl\\Idn\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Laurent Bassin",
+                    "email": "laurent@bassin.info"
+                },
+                {
+                    "name": "Trevor Rowbotham",
+                    "email": "trevor.rowbotham@pm.me"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "idn",
+                "intl",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.38.1"
+            },
+            "time": "2026-05-25T15:22:23+00:00"
+        },
+        {
+            "name": "symfony/polyfill-intl-normalizer",
+            "version": "v1.38.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-intl-normalizer/v1.38.0/symfony-polyfill-intl-normalizer-v1.38.0.zip",
+                "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "suggest": {
+                "ext-intl": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+                },
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for intl's Normalizer class and related functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "intl",
+                "normalizer",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.38.0"
+            },
+            "time": "2026-05-25T13:48:31+00:00"
+        },
+        {
+            "name": "symfony/polyfill-mbstring",
+            "version": "v1.38.2",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-mbstring/v1.38.2/symfony-polyfill-mbstring-v1.38.2.zip",
+                "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
+                "shasum": ""
+            },
+            "require": {
+                "ext-iconv": "*",
+                "php": ">=7.2"
+            },
+            "provide": {
+                "ext-mbstring": "*"
+            },
+            "suggest": {
+                "ext-mbstring": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Mbstring\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for the Mbstring extension",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "mbstring",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2"
+            },
+            "time": "2026-05-27T06:59:30+00:00"
+        },
+        {
+            "name": "symfony/polyfill-php80",
+            "version": "v1.37.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-php80/v1.37.0/symfony-polyfill-php80-v1.37.0.zip",
+                "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php80\\": ""
+                },
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Ion Bazan",
+                    "email": "ion.bazan@gmail.com"
+                },
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-php80/tree/v1.37.0"
+            },
+            "time": "2026-04-10T16:19:22+00:00"
+        },
+        {
+            "name": "symfony/polyfill-php83",
+            "version": "v1.38.2",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-php83/v1.38.2/symfony-polyfill-php83-v1.38.2.zip",
+                "reference": "796a26abb75ce49f3a84433cd81bf1009d73d5f8",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php83\\": ""
+                },
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-php83/tree/v1.38.2"
+            },
+            "time": "2026-05-27T06:51:48+00:00"
+        },
+        {
+            "name": "symfony/polyfill-php84",
+            "version": "v1.38.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-php84/v1.38.1/symfony-polyfill-php84-v1.38.1.zip",
+                "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php84\\": ""
+                },
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-php84/tree/v1.38.1"
+            },
+            "time": "2026-05-26T12:51:13+00:00"
+        },
+        {
+            "name": "symfony/polyfill-php85",
+            "version": "v1.38.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-php85/v1.38.1/symfony-polyfill-php85-v1.38.1.zip",
+                "reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php85\\": ""
+                },
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-php85/tree/v1.38.1"
+            },
+            "time": "2026-05-26T02:25:22+00:00"
+        },
+        {
+            "name": "symfony/service-contracts",
+            "version": "v3.7.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/service-contracts/v3.7.1/symfony-service-contracts-v3.7.1.zip",
+                "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.1",
+                "psr/container": "^1.1|^2.0",
+                "symfony/deprecation-contracts": "^2.5|^3"
+            },
+            "conflict": {
+                "ext-psr": "<1.1|>=2"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/contracts",
+                    "name": "symfony/contracts"
+                },
+                "branch-alias": {
+                    "dev-main": "3.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Contracts\\Service\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Test/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Generic abstractions related to writing services",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "abstractions",
+                "contracts",
+                "decoupling",
+                "interfaces",
+                "interoperability",
+                "standards"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/service-contracts/tree/v3.7.1"
+            },
+            "time": "2026-06-16T09:55:08+00:00"
+        },
+        {
+            "name": "symfony/string",
+            "version": "v7.4.13",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/string/v7.4.13/symfony-string-v7.4.13.zip",
+                "reference": "961683010db3b27ec6ebcd7308e6e1ee8fa7ffde",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.2",
+                "symfony/deprecation-contracts": "^2.5|^3.0",
+                "symfony/polyfill-ctype": "~1.8",
+                "symfony/polyfill-intl-grapheme": "~1.33",
+                "symfony/polyfill-intl-normalizer": "~1.0",
+                "symfony/polyfill-mbstring": "~1.0"
+            },
+            "conflict": {
+                "symfony/translation-contracts": "<2.5"
+            },
+            "require-dev": {
+                "symfony/emoji": "^7.1|^8.0",
+                "symfony/http-client": "^6.4|^7.0|^8.0",
+                "symfony/intl": "^6.4|^7.0|^8.0",
+                "symfony/translation-contracts": "^2.5|^3.0",
+                "symfony/var-exporter": "^6.4|^7.0|^8.0"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "Resources/functions.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Component\\String\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "grapheme",
+                "i18n",
+                "string",
+                "unicode",
+                "utf-8",
+                "utf8"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/string/tree/v7.4.13"
+            },
+            "time": "2026-05-23T15:23:29+00:00"
+        },
+        {
+            "name": "symfony/translation",
+            "version": "v7.4.14",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/translation/v7.4.14/symfony-translation-v7.4.14.zip",
+                "reference": "a1af4dacb24eb7ef4f1ca71b94da8ddbce572281",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.2",
+                "symfony/deprecation-contracts": "^2.5|^3",
+                "symfony/polyfill-mbstring": "~1.0",
+                "symfony/translation-contracts": "^2.5.3|^3.3"
+            },
+            "conflict": {
+                "nikic/php-parser": "<5.0",
+                "symfony/config": "<6.4",
+                "symfony/console": "<6.4",
+                "symfony/dependency-injection": "<6.4",
+                "symfony/http-client-contracts": "<2.5",
+                "symfony/http-kernel": "<6.4",
+                "symfony/service-contracts": "<2.5",
+                "symfony/twig-bundle": "<6.4",
+                "symfony/yaml": "<6.4"
+            },
+            "provide": {
+                "symfony/translation-implementation": "2.3|3.0"
+            },
+            "require-dev": {
+                "nikic/php-parser": "^5.0",
+                "psr/log": "^1|^2|^3",
+                "symfony/config": "^6.4|^7.0|^8.0",
+                "symfony/console": "^6.4|^7.0|^8.0",
+                "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+                "symfony/finder": "^6.4|^7.0|^8.0",
+                "symfony/http-client-contracts": "^2.5|^3.0",
+                "symfony/http-kernel": "^6.4|^7.0|^8.0",
+                "symfony/intl": "^6.4|^7.0|^8.0",
+                "symfony/polyfill-intl-icu": "^1.21",
+                "symfony/routing": "^6.4|^7.0|^8.0",
+                "symfony/service-contracts": "^2.5|^3",
+                "symfony/yaml": "^6.4|^7.0|^8.0"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "Resources/functions.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Component\\Translation\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Provides tools to internationalize your application",
+            "homepage": "https://symfony.com",
+            "support": {
+                "source": "https://github.com/symfony/translation/tree/v7.4.14"
+            },
+            "time": "2026-06-06T09:33:19+00:00"
+        },
+        {
+            "name": "symfony/translation-contracts",
+            "version": "v3.7.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/translation-contracts/v3.7.1/symfony-translation-contracts-v3.7.1.zip",
+                "reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.1"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/contracts",
+                    "name": "symfony/contracts"
+                },
+                "branch-alias": {
+                    "dev-main": "3.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Contracts\\Translation\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Test/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Generic abstractions related to translation",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "abstractions",
+                "contracts",
+                "decoupling",
+                "interfaces",
+                "interoperability",
+                "standards"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/translation-contracts/tree/v3.7.1"
+            },
+            "time": "2026-06-05T06:23:12+00:00"
+        },
+        {
+            "name": "symfony/var-dumper",
+            "version": "v7.4.14",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/var-dumper/v7.4.14/symfony-var-dumper-v7.4.14.zip",
+                "reference": "9a3a56a4a1e65a5cb4f8d13801fe8ab0a170e358",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.2",
+                "symfony/deprecation-contracts": "^2.5|^3",
+                "symfony/polyfill-mbstring": "~1.0"
+            },
+            "conflict": {
+                "symfony/console": "<6.4"
+            },
+            "require-dev": {
+                "symfony/console": "^6.4|^7.0|^8.0",
+                "symfony/http-kernel": "^6.4|^7.0|^8.0",
+                "symfony/process": "^6.4|^7.0|^8.0",
+                "symfony/uid": "^6.4|^7.0|^8.0",
+                "twig/twig": "^3.12"
+            },
+            "bin": [
+                "Resources/bin/var-dump-server"
+            ],
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "Resources/functions/dump.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Component\\VarDumper\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Provides mechanisms for walking through any arbitrary PHP variable",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "debug",
+                "dump"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/var-dumper/tree/v7.4.14"
+            },
+            "time": "2026-06-08T20:24:16+00:00"
+        },
+        {
+            "name": "symfony/var-exporter",
+            "version": "v7.4.14",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/var-exporter/v7.4.14/symfony-var-exporter-v7.4.14.zip",
+                "reference": "0118811b1d59f323bf131250b3fb919febfece28",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.2",
+                "symfony/deprecation-contracts": "^2.5|^3"
+            },
+            "require-dev": {
+                "symfony/property-access": "^6.4|^7.0|^8.0",
+                "symfony/serializer": "^6.4|^7.0|^8.0",
+                "symfony/var-dumper": "^6.4|^7.0|^8.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\VarExporter\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Allows exporting any serializable PHP data structure to plain PHP code",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "clone",
+                "construct",
+                "export",
+                "hydrate",
+                "instantiate",
+                "lazy-loading",
+                "proxy",
+                "serialize"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/var-exporter/tree/v7.4.14"
+            },
+            "time": "2026-06-27T08:41:53+00:00"
+        },
+        {
+            "name": "tinywan/storage",
+            "version": "v1.1.2",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/tinywan/storage/v1.1.2/tinywan-storage-v1.1.2.zip",
+                "reference": "a39584356829860fd2acab396ded3e6d730c71ae",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2",
+                "workerman/webman-framework": "^1.2.1||^2.0"
+            },
+            "require-dev": {
+                "aliyuncs/oss-sdk-php": "^2.4",
+                "friendsofphp/php-cs-fixer": "^3.6",
+                "league/flysystem-aws-s3-v3": "^1.0",
+                "phpstan/phpstan": "^1.4",
+                "phpunit/phpunit": "^9.5",
+                "qcloud/cos-sdk-v5": "^2.5",
+                "qiniu/php-sdk": "^7.4",
+                "workerman/webman": "^1.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Tinywan\\Storage\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "description": "webman storage plugin",
+            "support": {
+                "issues": "https://github.com/Tinywan/webman-storage/issues",
+                "source": "https://github.com/Tinywan/webman-storage/tree/v1.1.2"
+            },
+            "time": "2025-08-21T02:16:10+00:00"
+        },
+        {
+            "name": "topthink/think-container",
+            "version": "v3.0.2",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/topthink/think-container/v3.0.2/topthink-think-container-v3.0.2.zip",
+                "reference": "b2df244be1e7399ad4c8be1ccc40ed57868f730a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.0",
+                "psr/container": "^2.0",
+                "topthink/think-helper": "^3.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.5"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [],
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                }
+            ],
+            "description": "PHP Container & Facade Manager",
+            "support": {
+                "issues": "https://github.com/top-think/think-container/issues",
+                "source": "https://github.com/top-think/think-container/tree/v3.0.2"
+            },
+            "time": "2025-04-07T03:21:51+00:00"
+        },
+        {
+            "name": "topthink/think-helper",
+            "version": "v3.1.12",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/topthink/think-helper/v3.1.12/topthink-think-helper-v3.1.12.zip",
+                "reference": "fe277121112a8f1c872e169a733ca80bb11c4acb",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.5"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/helper.php"
+                ],
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "yunwuxin",
+                    "email": "448901948@qq.com"
+                }
+            ],
+            "description": "The ThinkPHP6 Helper Package",
+            "support": {
+                "issues": "https://github.com/top-think/think-helper/issues",
+                "source": "https://github.com/top-think/think-helper/tree/v3.1.12"
+            },
+            "time": "2025-12-26T09:58:29+00:00"
+        },
+        {
+            "name": "topthink/think-orm",
+            "version": "v4.0.51",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/topthink/think-orm/v4.0.51/topthink-think-orm-v4.0.51.zip",
+                "reference": "46abe2f824eb3bcb117d4c0ce93b203b592b79f7",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "ext-pdo": "*",
+                "php": ">=8.0.0",
+                "psr/log": ">=1.0",
+                "psr/simple-cache": "^3.0",
+                "topthink/think-helper": "^3.1",
+                "topthink/think-validate": "^3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.6|^10"
+            },
+            "suggest": {
+                "ext-mongodb": "provide mongodb support"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/helper.php",
+                    "stubs/load_stubs.php"
+                ],
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                }
+            ],
+            "description": "the PHP Database&ORM Framework",
+            "keywords": [
+                "database",
+                "orm"
+            ],
+            "support": {
+                "issues": "https://github.com/top-think/think-orm/issues",
+                "source": "https://github.com/top-think/think-orm/tree/v4.0.51"
+            },
+            "time": "2025-12-18T13:11:52+00:00"
+        },
+        {
+            "name": "topthink/think-validate",
+            "version": "v3.0.7",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/topthink/think-validate/v3.0.7/topthink-think-validate-v3.0.7.zip",
+                "reference": "85063f6d4ef8ed122f17a36179dc3e0949b30988",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.0",
+                "topthink/think-container": ">=3.0"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/helper.php"
+                ],
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                }
+            ],
+            "description": "think validate",
+            "support": {
+                "issues": "https://github.com/top-think/think-validate/issues",
+                "source": "https://github.com/top-think/think-validate/tree/v3.0.7"
+            },
+            "time": "2025-06-11T05:51:40+00:00"
+        },
+        {
+            "name": "vlucas/phpdotenv",
+            "version": "v5.6.4",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/vlucas/phpdotenv/v5.6.4/vlucas-phpdotenv-v5.6.4.zip",
+                "reference": "416df702837983f8d5ff48c9c3fee4f5f57b980b",
+                "shasum": ""
+            },
+            "require": {
+                "ext-pcre": "*",
+                "graham-campbell/result-type": "^1.1.4",
+                "php": "^7.2.5 || ^8.0",
+                "phpoption/phpoption": "^1.9.5",
+                "symfony/polyfill-ctype": "^1.26",
+                "symfony/polyfill-mbstring": "^1.26",
+                "symfony/polyfill-php80": "^1.26"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.2",
+                "ext-filter": "*",
+                "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2"
+            },
+            "suggest": {
+                "ext-filter": "Required to use the boolean validator."
+            },
+            "type": "library",
+            "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                },
+                "branch-alias": {
+                    "dev-master": "5.6-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Dotenv\\": "src/"
+                }
+            },
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Vance Lucas",
+                    "email": "vance@vancelucas.com",
+                    "homepage": "https://github.com/vlucas"
+                }
+            ],
+            "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.",
+            "keywords": [
+                "dotenv",
+                "env",
+                "environment"
+            ],
+            "support": {
+                "issues": "https://github.com/vlucas/phpdotenv/issues",
+                "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.4"
+            },
+            "time": "2026-07-06T19:11:50+00:00"
+        },
+        {
+            "name": "voku/portable-ascii",
+            "version": "2.1.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/voku/portable-ascii/2.1.1/voku-portable-ascii-2.1.1.zip",
+                "reference": "8e1051fe39379367aecf014f41744ce7539a856f",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~8.5 || ~9.6 || ~10.5 || ~11.5"
+            },
+            "suggest": {
+                "ext-intl": "Use Intl for transliterator_transliterate() support"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "voku\\": "src/voku/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Lars Moelleken",
+                    "homepage": "https://www.moelleken.org/"
+                }
+            ],
+            "description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
+            "homepage": "https://github.com/voku/portable-ascii",
+            "keywords": [
+                "ascii",
+                "clean",
+                "php"
+            ],
+            "support": {
+                "issues": "https://github.com/voku/portable-ascii/issues",
+                "source": "https://github.com/voku/portable-ascii/tree/2.1.1"
+            },
+            "time": "2026-04-26T05:33:54+00:00"
+        },
+        {
+            "name": "webman/console",
+            "version": "v2.2.3",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/webman/console/v2.2.3/webman-console-v2.2.3.zip",
+                "reference": "df5fffe07efd61d99dacacde9dd41a899ae923c4",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/inflector": "^2.0",
+                "php": ">=8.1",
+                "symfony/console": "^6.1 || ^7.0"
+            },
+            "require-dev": {
+                "workerman/webman": "^2.1"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Webman\\Console\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "walkor",
+                    "email": "walkor@workerman.net",
+                    "homepage": "http://www.workerman.net",
+                    "role": "Developer"
+                }
+            ],
+            "description": "Webman console",
+            "homepage": "http://www.workerman.net",
+            "keywords": [
+                "webman console"
+            ],
+            "support": {
+                "email": "walkor@workerman.net",
+                "forum": "http://www.workerman.net/questions",
+                "issues": "https://github.com/webman-php/console/issues",
+                "source": "https://github.com/webman-php/console",
+                "wiki": "http://www.workerman.net/doc/webman"
+            },
+            "time": "2026-03-29T08:32:39+00:00"
+        },
+        {
+            "name": "webman/event",
+            "version": "v1.0.5",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/webman/event/v1.0.5/webman-event-v1.0.5.zip",
+                "reference": "b1c3f6b70fd290e48288703d59bead0e28f9fb84",
+                "shasum": ""
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Webman\\Event\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "description": "Webman event plugin",
+            "support": {
+                "issues": "https://github.com/webman-php/event/issues",
+                "source": "https://github.com/webman-php/event/tree/v1.0.5"
+            },
+            "time": "2023-12-04T09:22:12+00:00"
+        },
+        {
+            "name": "webman/redis",
+            "version": "v2.1.5",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/webman/redis/v2.1.5/webman-redis-v2.1.5.zip",
+                "reference": "aadc69937217494c9acaa6d6b4fe8bcaa64eb6e6",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/redis": "^10.0 || ^11.0 || ^12.0 || ^13.0",
+                "workerman/webman-framework": "^2.1 || dev-master"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "support\\": "src/support",
+                    "Webman\\Redis\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "description": "Webman redis",
+            "support": {
+                "issues": "https://github.com/webman-php/redis/issues",
+                "source": "https://github.com/webman-php/redis/tree/v2.1.5"
+            },
+            "time": "2026-03-25T02:00:19+00:00"
+        },
+        {
+            "name": "webman/redis-queue",
+            "version": "v2.1.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/webman/redis-queue/v2.1.1/webman-redis-queue-v2.1.1.zip",
+                "reference": "ff4791e21f3c324a47e21da7b6f2dae5a7311dcb",
+                "shasum": ""
+            },
+            "require": {
+                "ext-redis": "*",
+                "php": ">=8.1",
+                "workerman/redis-queue": "^1.2",
+                "workerman/webman-framework": "^2.1 || dev-master"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Webman\\RedisQueue\\": "./src"
+                }
+            },
+            "description": "Redis message queue plugin for webman.",
+            "support": {
+                "issues": "https://github.com/webman-php/redis-queue/issues",
+                "source": "https://github.com/webman-php/redis-queue/tree/v2.1.1"
+            },
+            "time": "2025-11-14T07:12:52+00:00"
+        },
+        {
+            "name": "webman/think-cache",
+            "version": "v2.1.6",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/webman/think-cache/v2.1.6/webman-think-cache-v2.1.6.zip",
+                "reference": "936fe91fc5781a44f82262e805c60efbab262718",
+                "shasum": ""
+            },
+            "require": {
+                "psr/simple-cache": "^1.0|^2.0|^3.0",
+                "topthink/think-container": "^2.0|^3.0",
+                "workerman/webman-framework": "^2.1 || dev-master"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "support\\": "src/support",
+                    "Webman\\ThinkCache\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "support": {
+                "issues": "https://github.com/webman-php/think-cache/issues",
+                "source": "https://github.com/webman-php/think-cache/tree/v2.1.6"
+            },
+            "time": "2026-04-29T00:26:47+00:00"
+        },
+        {
+            "name": "webman/think-orm",
+            "version": "v2.1.11",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/webman/think-orm/v2.1.11/webman-think-orm-v2.1.11.zip",
+                "reference": "81fb87a085ceb2d25be5e86da12befbbbfe70c0e",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.1",
+                "topthink/think-container": "^2.0|^3.0",
+                "topthink/think-orm": "^2.0.53 || ^3.0.0 || ^4.0.30 || dev-master",
+                "workerman/webman-framework": "^2.1 || dev-master"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "support\\": "src/support",
+                    "Webman\\ThinkOrm\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "support": {
+                "issues": "https://github.com/webman-php/think-orm/issues",
+                "source": "https://github.com/webman-php/think-orm/tree/v2.1.11"
+            },
+            "time": "2026-03-25T01:34:20+00:00"
+        },
+        {
+            "name": "webman/validation",
+            "version": "v2.2.1",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/webman/validation/v2.2.1/webman-validation-v2.2.1.zip",
+                "reference": "d5117162aed293955fc55ee02a01d9300b226aaa",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/translation": "*",
+                "illuminate/validation": "*",
+                "webman/console": ">=2.1.7",
+                "workerman/webman-framework": "^2.1 || dev-master"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Webman\\Validation\\": "src",
+                    "support\\validation\\": "src/support/validation"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "description": "Webman plugin webman/validation",
+            "support": {
+                "issues": "https://github.com/webman-php/validation/issues",
+                "source": "https://github.com/webman-php/validation/tree/v2.2.1"
+            },
+            "time": "2026-02-26T03:10:51+00:00"
+        },
+        {
+            "name": "workerman/coroutine",
+            "version": "v1.1.5",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/workerman/coroutine/v1.1.5/workerman-coroutine-v1.1.5.zip",
+                "reference": "b60e44267b90d398dbfa7a320f3e97b46357ac9f",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.1",
+                "workerman/workerman": "^5.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^11.0",
+                "psr/log": "*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Workerman\\": "src",
+                    "Workerman\\Coroutine\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "description": "Workerman coroutine",
+            "support": {
+                "issues": "https://github.com/workerman-php/coroutine/issues",
+                "source": "https://github.com/workerman-php/coroutine/tree/v1.1.5"
+            },
+            "time": "2026-03-12T02:07:37+00:00"
+        },
+        {
+            "name": "workerman/crontab",
+            "version": "v1.0.7",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/workerman/crontab/v1.0.7/workerman-crontab-v1.0.7.zip",
+                "reference": "74f51ca8204e8eb628e57bc0e640561d570da2cb",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.0",
+                "workerman/workerman": ">=4.0.20"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Workerman\\Crontab\\": "./src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "walkor",
+                    "email": "walkor@workerman.net",
+                    "homepage": "http://www.workerman.net",
+                    "role": "Developer"
+                }
+            ],
+            "description": "A crontab written in PHP based on workerman",
+            "homepage": "http://www.workerman.net",
+            "keywords": [
+                "crontab"
+            ],
+            "support": {
+                "email": "walkor@workerman.net",
+                "forum": "http://wenda.workerman.net/",
+                "issues": "https://github.com/walkor/workerman/issues",
+                "source": "https://github.com/walkor/crontab",
+                "wiki": "http://doc.workerman.net/"
+            },
+            "time": "2025-01-15T07:20:50+00:00"
+        },
+        {
+            "name": "workerman/redis",
+            "version": "v2.0.6",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/workerman/redis/v2.0.6/workerman-redis-v2.0.6.zip",
+                "reference": "d8800cba4c9b65e128897932f741ec89ecfbc339",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7",
+                "workerman/workerman": "^4.1.0||^5.0.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Workerman\\Redis\\": "./src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "homepage": "http://www.workerman.net",
+            "support": {
+                "issues": "https://github.com/workerman-php/redis/issues",
+                "source": "https://github.com/workerman-php/redis/tree/v2.0.6"
+            },
+            "time": "2026-06-02T07:34:24+00:00"
+        },
+        {
+            "name": "workerman/redis-queue",
+            "version": "v1.2.2",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/workerman/redis-queue/v1.2.2/workerman-redis-queue-v1.2.2.zip",
+                "reference": "f0ba4ea9143ae02f39b998ed908d107354cb43c0",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.0",
+                "workerman/redis": "^1.0||^2.0",
+                "workerman/workerman": ">=4.0.20"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Workerman\\RedisQueue\\": "./src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "description": "Message queue system written in PHP based on workerman and backed by Redis.",
+            "homepage": "http://www.workerman.net",
+            "support": {
+                "issues": "https://github.com/walkor/redis-queue/issues",
+                "source": "https://github.com/walkor/redis-queue/tree/v1.2.2"
+            },
+            "time": "2026-01-20T14:57:09+00:00"
+        },
+        {
+            "name": "workerman/webman-framework",
+            "version": "v2.2.2",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/workerman/webman-framework/v2.2.2/workerman-webman-framework-v2.2.2.zip",
+                "reference": "4b761c0c44778618a5d9b9641fa6168fa06f95c4",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "nikic/fast-route": "^1.3",
+                "php": ">=8.1",
+                "psr/container": ">=1.0",
+                "psr/log": "^2.0 || ^3.0",
+                "workerman/workerman": "^5.1 || dev-master"
+            },
+            "suggest": {
+                "ext-event": "For better performance. "
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "./src/support/helpers.php"
+                ],
+                "psr-4": {
+                    "Webman\\": "./src",
+                    "Support\\": "./src/support",
+                    "support\\": "./src/support",
+                    "Support\\View\\": "./src/support/view",
+                    "Support\\Bootstrap\\": "./src/support/bootstrap",
+                    "Support\\Exception\\": "./src/support/exception"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "walkor",
+                    "email": "walkor@workerman.net",
+                    "homepage": "https://www.workerman.net",
+                    "role": "Developer"
+                }
+            ],
+            "description": "High performance HTTP Service Framework.",
+            "homepage": "https://www.workerman.net",
+            "keywords": [
+                "High Performance",
+                "http service"
+            ],
+            "support": {
+                "email": "walkor@workerman.net",
+                "forum": "https://wenda.workerman.net/",
+                "issues": "https://github.com/walkor/webman/issues",
+                "source": "https://github.com/walkor/webman-framework",
+                "wiki": "https://doc.workerman.net/"
+            },
+            "time": "2026-07-08T03:33:00+00:00"
+        },
+        {
+            "name": "workerman/workerman",
+            "version": "v5.2.2",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/workerman/workerman/v5.2.2/workerman-workerman-v5.2.2.zip",
+                "reference": "a0866601af066c0eab5a2f7b9aef8bdda8fa1911",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "php": ">=8.1",
+                "workerman/coroutine": "^1.1 || dev-main"
+            },
+            "conflict": {
+                "ext-swow": "<v1.0.0"
+            },
+            "require-dev": {
+                "guzzlehttp/guzzle": "^7.10",
+                "mockery/mockery": "^1.6.12",
+                "pestphp/pest": "^2.36 || ^3 || ^4",
+                "phpstan/phpstan": "^2.1"
+            },
+            "suggest": {
+                "ext-event": "For better performance. "
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Workerman\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "walkor",
+                    "email": "walkor@workerman.net",
+                    "homepage": "https://www.workerman.net",
+                    "role": "Developer"
+                }
+            ],
+            "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.",
+            "homepage": "https://www.workerman.net",
+            "keywords": [
+                "asynchronous",
+                "event-loop",
+                "framework",
+                "http"
+            ],
+            "support": {
+                "email": "walkor@workerman.net",
+                "forum": "https://www.workerman.net/questions",
+                "issues": "https://github.com/walkor/workerman/issues",
+                "source": "https://github.com/walkor/workerman",
+                "wiki": "https://www.workerman.net/doc/workerman/"
+            },
+            "time": "2026-06-04T07:31:34+00:00"
+        },
+        {
+            "name": "yzh52521/easyhttp",
+            "version": "v1.1.3",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/yzh52521/easyhttp/v1.1.3/yzh52521-easyhttp-v1.1.3.zip",
+                "reference": "02bcf47eaf723520fa3905d0e6f1852168fe646c",
+                "shasum": ""
+            },
+            "require": {
+                "guzzlehttp/guzzle": "^6.0|^7.0",
+                "php": ">=7.2.5",
+                "psr/log": "^1.0|^2.0|^3.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "yzh52521\\EasyHttp\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "yzh52521",
+                    "email": "396751927@qq.com"
+                }
+            ],
+            "description": "EasyHttp 是一个轻量级、语义化、对IDE友好的HTTP客户端,支持常见的HTTP请求、异步请求和并发请求,让你可以快速地使用 HTTP 请求与其他 Web 应用进行通信。",
+            "homepage": "https://github.com/yzh52521/easyhttp",
+            "keywords": [
+                "EasyHttp",
+                "curl",
+                "easy-http",
+                "http",
+                "php",
+                "php-http",
+                "phphttp"
+            ],
+            "support": {
+                "issues": "https://github.com/yuanzhihai/easyhttp/issues",
+                "source": "https://github.com/yuanzhihai/easyhttp/tree/v1.1.3"
+            },
+            "time": "2023-11-14T05:49:02+00:00"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "dev",
+    "stability-flags": [],
+    "prefer-stable": true,
+    "prefer-lowest": false,
+    "platform": {
+        "php": ">=8.1"
+    },
+    "platform-dev": [],
+    "plugin-api-version": "2.6.0"
+}

+ 26 - 0
config/app.php

@@ -0,0 +1,26 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+use support\Request;
+
+return [
+    'debug' => true,
+    'error_reporting' => E_ALL,
+    'default_timezone' => 'Asia/Shanghai',
+    'request_class' => Request::class,
+    'public_path' => base_path() . DIRECTORY_SEPARATOR . 'public',
+    'runtime_path' => base_path(false) . DIRECTORY_SEPARATOR . 'runtime',
+    'controller_suffix' => 'Controller',
+    'controller_reuse' => false,
+];

+ 21 - 0
config/autoload.php

@@ -0,0 +1,21 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+    'files' => [
+        base_path() . '/app/functions.php',
+        base_path() . '/support/Request.php',
+        base_path() . '/support/Response.php',
+    ]
+];

+ 18 - 0
config/bootstrap.php

@@ -0,0 +1,18 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+    support\bootstrap\Session::class,
+    Webman\ThinkOrm\ThinkOrm::class,
+];

+ 7 - 0
config/container.php

@@ -0,0 +1,7 @@
+<?php
+
+$builder = new \DI\ContainerBuilder();
+$builder->addDefinitions(config('dependence', []));
+$builder->useAutowiring(true);
+$builder->useAttributes(true);
+return $builder->build();

+ 15 - 0
config/dependence.php

@@ -0,0 +1,15 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [];

+ 5 - 0
config/event.php

@@ -0,0 +1,5 @@
+<?php
+
+return [
+    
+];

+ 17 - 0
config/exception.php

@@ -0,0 +1,17 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+    '' => support\exception\Handler::class,
+];

+ 32 - 0
config/log.php

@@ -0,0 +1,32 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+    'default' => [
+        'handlers' => [
+            [
+                'class' => Monolog\Handler\RotatingFileHandler::class,
+                'constructor' => [
+                    runtime_path() . '/logs/webman.log',
+                    7, //$maxFiles
+                    Monolog\Logger::DEBUG,
+                ],
+                'formatter' => [
+                    'class' => Monolog\Formatter\LineFormatter::class,
+                    'constructor' => [null, 'Y-m-d H:i:s', true],
+                ],
+            ]
+        ],
+    ],
+];

+ 15 - 0
config/middleware.php

@@ -0,0 +1,15 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [];

+ 48 - 0
config/plugin/linfly/annotation/annotation.php

@@ -0,0 +1,48 @@
+<?php
+
+/**
+ * Created by PhpStorm.
+ * User: LinFei
+ * Created time 2022/10/10 10:57:15
+ * E-mail: fly@eyabc.cn
+ */
+declare (strict_types=1);
+
+return [
+    // 注解扫描路径
+    'include_paths' => [
+        // 应用目录 支持通配符: * , 例如: app/*, app/*.php
+        'app',
+    ],
+    // 扫描排除的路径 支持通配符: *
+    'exclude_paths' => [
+        'app/model'
+    ],
+    // 忽略的进程名称
+    'ignore_process' => [
+        'monitor'
+    ],
+    // 路由设置
+    'route' => [
+        // 如果注解路由 @Route() 未传参则默认使用方法名作为path
+        'use_default_method' => true,
+    ],
+    // 验证器注解
+    'validate' => [
+        // 验证器验证处理类 (该功能需要自行安装对应的验证器扩展包),目前只支持 think-validate
+        'handle' => LinFly\Annotation\Validate\Handle\ThinkValidate::class,
+        // 验证失败处理方法
+        'fail_handle' => function (Webman\Http\Request $request, string $message) {
+            return json(['code' => 500, 'msg' => $message]);
+        },
+
+        // 注解验证器 @Validate() 未填写验证器类名时则通过命名空间拼接规则获取验证器类名
+        'auto_validate' => true,
+        // 验证器类名后缀
+        'auto_validate_suffix' => 'Validate',
+        // 自动验证器验证处理
+        // 'auto_validate_handle' => function (array $item): string {
+        //     return str_replace('\\controller\\', '\\validate\\', $item['class']);
+        // }
+    ],
+];

+ 4 - 0
config/plugin/linfly/annotation/app.php

@@ -0,0 +1,4 @@
+<?php
+return [
+    'enable' => true,
+];

+ 19 - 0
config/plugin/linfly/annotation/bootstrap.php

@@ -0,0 +1,19 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+namespace LinFly\Annotation\Bootstrap;
+
+return [
+    AnnotationBootstrap::class
+];

+ 19 - 0
config/plugin/linfly/annotation/middleware.php

@@ -0,0 +1,19 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+    '' => [
+        LinFly\Annotation\Validate\ValidateMiddleware::class
+    ]
+];

+ 17 - 0
config/plugin/linfly/annotation/route.php

@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * Created by PhpStorm.
+ * User: LinFei
+ * Created time 2022/10/10 10:52:22
+ * E-mail: fly@eyabc.cn
+ */
+declare (strict_types=1);
+
+namespace LinFly\Annotation\Parser;
+
+use LinFly\Annotation\Bootstrap\AnnotationBootstrap;
+
+if (!AnnotationBootstrap::isIgnoreProcess()) {
+    RouteAnnotationParser::createRoute();
+}

+ 71 - 0
config/plugin/shopwwi/auth/app.php

@@ -0,0 +1,71 @@
+<?php
+
+ return [
+     'enable' => true,
+     'app_key' => 'base64:N721v3Gt2I58HH7oiU7a70PQ+i8ekPWRqwI+JSnM1wo=',
+     'guard' => [
+         'user' => [
+             'key' => 'id',
+             'field' => ['id','name','email','mobile'], //设置允许写入扩展中的字段
+             'num' => 0, //-1为不限制终端数量 0为只支持一个终端在线 大于0为同一账号同终端支持数量 建议设置为1 则同一账号同终端在线1个
+             'model'=> app\model\Test::class // 当为数组时 [app\model\Test::class,'thinkphp'] 来说明模型归属
+         ]
+     ],
+     'jwt' => [
+         'redis' => false,
+         // redis前缀
+         'redis_prefix' => '',
+         // 算法类型 ES256、HS256、HS384、HS512、RS256、RS384、RS512
+         'algorithms' => 'HS256',
+         // access令牌秘钥
+         'access_secret_key' => 'w5LgNx5luRRjmamZFSqz3cPHOp9KuQPExlvgi18DN4SdnSI9obcVEhiZVE0NIIC7',
+         // access令牌过期时间,单位秒。默认 2 小时
+         'access_exp' => 36000,
+         // refresh令牌秘钥
+         'refresh_secret_key' => 'w5LgNx5luRRjmamZFSqz3cPHOp9KuQPExlvgi18DN4SdnSI9obcVEhiZVE0NIIC7',
+         // refresh令牌过期时间,单位秒。默认 7 天
+         'refresh_exp' => 72000,
+         // 令牌签发者
+         'iss' => 'webman',
+         // 令牌签发时间
+         'iat' => time(),
+
+         /**
+          * access令牌 RS256 私钥
+          * 生成RSA私钥(Linux系统):openssl genrsa -out access_private_key.key 1024 (2048)
+          */
+         'access_private_key' => <<<EOD
+-----BEGIN RSA PRIVATE KEY-----
+...
+-----END RSA PRIVATE KEY-----
+EOD,
+         /**
+          * access令牌 RS256 公钥
+          * 生成RSA公钥(Linux系统):openssl rsa -in access_private_key.key -pubout -out access_public_key.key
+          */
+         'access_public_key' => <<<EOD
+-----BEGIN PUBLIC KEY-----
+...
+-----END PUBLIC KEY-----
+EOD,
+
+         /**
+          * refresh令牌 RS256 私钥
+          * 生成RSA私钥(Linux系统):openssl genrsa -out refresh_private_key.key 1024 (2048)
+          */
+         'refresh_private_key' => <<<EOD
+-----BEGIN RSA PRIVATE KEY-----
+...
+-----END RSA PRIVATE KEY-----
+EOD,
+         /**
+          * refresh令牌 RS256 公钥
+          * 生成RSA公钥(Linux系统):openssl rsa -in refresh_private_key.key -pubout -out refresh_public_key.key
+          */
+         'refresh_public_key' => <<<EOD
+-----BEGIN PUBLIC KEY-----
+...
+-----END PUBLIC KEY-----
+EOD,
+     ],
+ ];

+ 76 - 0
config/plugin/tinywan/storage/app.php

@@ -0,0 +1,76 @@
+<?php
+/**
+ * @desc app.php 描述信息
+ *
+ * @author Tinywan(ShaoBo Wan)
+ * @date 2022/3/10 19:46
+ */
+
+return [
+    'enable' => true,
+    'storage' => [
+        'default' => 'local', // local:本地 oss:阿里云 cos:腾讯云 qos:七牛云
+        'single_limit' => 1024 * 1024 * 200, // 单个文件的大小限制,默认200M 1024 * 1024 * 200
+        'total_limit' => 1024 * 1024 * 200, // 所有文件的大小限制,默认200M 1024 * 1024 * 200
+        'nums' => 10, // 文件数量限制,默认10
+        'include' => [], // 被允许的文件类型列表
+        'exclude' => [], // 不被允许的文件类型列表
+        // 本地对象存储
+        'local' => [
+            'adapter' => \Tinywan\Storage\Adapter\LocalAdapter::class,
+            'root' => runtime_path().'/storage',
+            'dirname' => function () {
+                return date('Ymd');
+            },
+            'domain' => 'http://127.0.0.1:8787',
+            'uri' => '/runtime', // 如果 domain + uri 不在 public 目录下,请做好软链接,否则生成的url无法访问
+            'algo' => 'sha1',
+        ],
+        // 阿里云对象存储
+        'oss' => [
+            'adapter' => \Tinywan\Storage\Adapter\OssAdapter::class,
+            'accessKeyId' => 'xxxxxxxxxxxx',
+            'accessKeySecret' => 'xxxxxxxxxxxx',
+            'bucket' => 'resty-webman',
+            'dirname' => function () {
+                return 'storage';
+            },
+            'domain' => 'http://webman.oss.tinywan.com',
+            'endpoint' => 'oss-cn-hangzhou.aliyuncs.com',
+            'algo' => 'sha1',
+        ],
+        // 腾讯云对象存储
+        'cos' => [
+            'adapter' => \Tinywan\Storage\Adapter\CosAdapter::class,
+            'secretId' => 'xxxxxxxxxxxxx',
+            'secretKey' => 'xxxxxxxxxxxx',
+            'bucket' => 'resty-webman-xxxxxxxxx',
+            'dirname' => 'storage',
+            'domain' => 'http://webman.oss.tinywan.com',
+            'region' => 'ap-shanghai',
+        ],
+        // 七牛云对象存储
+        'qiniu' => [
+            'adapter' => \Tinywan\Storage\Adapter\QiniuAdapter::class,
+            'accessKey' => 'xxxxxxxxxxxxx',
+            'secretKey' => 'xxxxxxxxxxxxx',
+            'bucket' => 'resty-webman',
+            'dirname' => 'storage',
+            'domain' => 'http://webman.oss.tinywan.com',
+        ],
+        // aws
+        's3' => [
+            'adapter' => \Tinywan\Storage\Adapter\S3Adapter::class,
+            'key' => 'xxxxxxxxxxxxx',
+            'secret' => 'xxxxxxxxxxxxx',
+            'bucket' => 'resty-webman',
+            'dirname' => 'storage',
+            'domain' => 'http://webman.oss.tinywan.com',
+            'region' => 'S3_REGION',
+            'version' => 'latest',
+            'use_path_style_endpoint' => true,
+            'endpoint' => 'S3_ENDPOINT',
+            'acl' => 'public-read',
+        ],
+    ],
+];

+ 28 - 0
config/plugin/webman/console/app.php

@@ -0,0 +1,28 @@
+<?php
+return [
+    'enable' => true,
+
+    'build_dir'  => BASE_PATH . DIRECTORY_SEPARATOR . 'build',
+
+    'phar_filename' => 'webman.phar',
+
+    'phar_format' => Phar::PHAR, // Phar archive format: Phar::PHAR, Phar::TAR, Phar::ZIP
+
+    'phar_compression' => Phar::NONE, // Compression method for Phar archive: Phar::NONE, Phar::GZ, Phar::BZ2
+
+    'bin_filename' => 'webman.bin',
+
+    'signature_algorithm'=> Phar::SHA256, //set the signature algorithm for a phar and apply it. The signature algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512, or Phar::OPENSSL.
+
+    'private_key_file'  => '', // The file path for certificate or OpenSSL private key file.
+
+    'exclude_pattern'   => '#^(?!.*(composer.json|/.github/|/.idea/|/.git/|/.setting/|/runtime/|/vendor-bin/|/build/|/vendor/webman/admin/))(.*)$#',
+
+    'exclude_files'     => [
+        '.env', 'LICENSE', 'composer.json', 'composer.lock', 'start.php', 'webman.phar', 'webman.bin'
+    ],
+
+    'custom_ini' => '
+memory_limit = 256M
+    ',
+];

+ 4 - 0
config/plugin/webman/event/app.php

@@ -0,0 +1,4 @@
+<?php
+return [
+    'enable' => true,
+];

+ 17 - 0
config/plugin/webman/event/bootstrap.php

@@ -0,0 +1,17 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+    Webman\Event\BootStrap::class,
+];

+ 7 - 0
config/plugin/webman/event/command.php

@@ -0,0 +1,7 @@
+<?php
+
+use Webman\Event\EventListCommand;
+
+return [
+    EventListCommand::class
+];

+ 4 - 0
config/plugin/webman/redis-queue/app.php

@@ -0,0 +1,4 @@
+<?php
+return [
+    'enable' => true,
+];

+ 7 - 0
config/plugin/webman/redis-queue/command.php

@@ -0,0 +1,7 @@
+<?php
+
+use Webman\RedisQueue\Command\MakeConsumerCommand;
+
+return [
+    MakeConsumerCommand::class
+];

+ 32 - 0
config/plugin/webman/redis-queue/log.php

@@ -0,0 +1,32 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+    'default' => [
+        'handlers' => [
+            [
+                'class' => Monolog\Handler\RotatingFileHandler::class,
+                'constructor' => [
+                    runtime_path() . '/logs/redis-queue/queue.log',
+                    7, //$maxFiles
+                    Monolog\Logger::DEBUG,
+                ],
+                'formatter' => [
+                    'class' => Monolog\Formatter\LineFormatter::class,
+                    'constructor' => [null, 'Y-m-d H:i:s', true],
+                ],
+            ]
+        ],
+    ]
+];

+ 11 - 0
config/plugin/webman/redis-queue/process.php

@@ -0,0 +1,11 @@
+<?php
+return [
+    'consumer'  => [
+        'handler'     => Webman\RedisQueue\Process\Consumer::class,
+        'count'       => 8, // 可以设置多进程同时消费
+        'constructor' => [
+            // 消费者类目录
+            'consumer_dir' => app_path() . '/queue/redis'
+        ]
+    ]
+];

+ 21 - 0
config/plugin/webman/redis-queue/redis.php

@@ -0,0 +1,21 @@
+<?php
+return [
+    'default' => [
+        'host' => 'redis://127.0.0.1:6379',
+        'options' => [
+            'auth' => null,
+            'db' => 0,
+            'prefix' => '',
+            'max_attempts'  => 5,
+            'retry_seconds' => 5,
+        ],
+        // Connection pool, supports only Swoole or Swow drivers.
+        'pool' => [
+            'max_connections' => 5,
+            'min_connections' => 1,
+            'wait_timeout' => 3,
+            'idle_timeout' => 60,
+            'heartbeat_interval' => 50,
+        ]
+    ],
+];

+ 8 - 0
config/plugin/webman/validation/app.php

@@ -0,0 +1,8 @@
+<?php
+
+use support\validation\ValidationException;
+
+return [
+    'enable' => true,
+    'exception' => ValidationException::class,
+];

+ 7 - 0
config/plugin/webman/validation/command.php

@@ -0,0 +1,7 @@
+<?php
+
+use Webman\Validation\Command\MakeValidatorCommand;
+
+return [
+    MakeValidatorCommand::class
+];

+ 9 - 0
config/plugin/webman/validation/middleware.php

@@ -0,0 +1,9 @@
+<?php
+
+use Webman\Validation\Middleware;
+
+return [
+    '@' => [
+        Middleware::class,
+    ],
+];

+ 50 - 0
config/process.php

@@ -0,0 +1,50 @@
+<?php
+
+use support\Log;
+use support\Request;
+use app\process\Http;
+
+global $argv;
+
+return [
+    'poem' => [
+        'handler' => Http::class,
+        'listen' => 'http://0.0.0.0:7881',
+        'count' => cpu_count() * 4,
+        'user' => '',
+        'group' => '',
+        'reusePort' => false,
+        'eventLoop' => '',
+        'context' => [],
+        'constructor' => [
+            'requestClass' => Request::class,
+            'logger' => Log::channel('default'),
+            'appPath' => app_path(),
+            'publicPath' => public_path()
+        ]
+    ],
+    // File update detection and automatic reload
+    'monitor' => [
+        'handler' => app\process\Monitor::class,
+        'reloadable' => false,
+        'constructor' => [
+            // Monitor these directories
+            'monitorDir' => array_merge([
+                app_path(),
+                config_path(),
+                base_path() . '/process',
+                base_path() . '/support',
+                base_path() . '/resource',
+                base_path() . '/.env',
+            ], glob(base_path() . '/plugin/*/app'), glob(base_path() . '/plugin/*/config'), glob(base_path() . '/plugin/*/api')),
+            // Files with these suffixes will be monitored
+            'monitorExtensions' => [
+                'php', 'html', 'htm', 'env'
+            ],
+            'options' => [
+                'enable_file_monitor' => !in_array('-d', $argv) && DIRECTORY_SEPARATOR === '/',
+                'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/',
+            ]
+        ]
+    ]
+];

+ 29 - 0
config/redis.php

@@ -0,0 +1,29 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+    'default' => [
+        'password' => '',
+        'host' => '127.0.0.1',
+        'port' => 6379,
+        'database' => 0,
+        'pool' => [
+            'max_connections' => 5,
+            'min_connections' => 1,
+            'wait_timeout' => 3,
+            'idle_timeout' => 60,
+            'heartbeat_interval' => 50,
+        ],
+    ]
+];

+ 21 - 0
config/route.php

@@ -0,0 +1,21 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+use Webman\Route;
+
+
+
+
+
+

+ 23 - 0
config/server.php

@@ -0,0 +1,23 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+    'event_loop' => '',
+    'stop_timeout' => 2,
+    'pid_file' => runtime_path() . '/webman.pid',
+    'status_file' => runtime_path() . '/webman.status',
+    'stdout_file' => runtime_path() . '/logs/stdout.log',
+    'log_file' => runtime_path() . '/logs/workerman.log',
+    'max_package_size' => 10 * 1024 * 1024
+];

+ 65 - 0
config/session.php

@@ -0,0 +1,65 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+use Webman\Session\FileSessionHandler;
+use Webman\Session\RedisSessionHandler;
+use Webman\Session\RedisClusterSessionHandler;
+
+return [
+
+    'type' => 'file', // or redis or redis_cluster
+
+    'handler' => FileSessionHandler::class,
+
+    'config' => [
+        'file' => [
+            'save_path' => runtime_path() . '/sessions',
+        ],
+        'redis' => [
+            'host' => '127.0.0.1',
+            'port' => 6379,
+            'auth' => '',
+            'timeout' => 2,
+            'database' => '',
+            'prefix' => 'redis_session_',
+        ],
+        'redis_cluster' => [
+            'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'],
+            'timeout' => 2,
+            'auth' => '',
+            'prefix' => 'redis_session_',
+        ]
+    ],
+
+    'session_name' => 'PHPSID',
+    
+    'auto_update_timestamp' => false,
+
+    'lifetime' => 7*24*60*60,
+
+    'cookie_lifetime' => 365*24*60*60,
+
+    'cookie_path' => '/',
+
+    'domain' => '',
+    
+    'http_only' => true,
+
+    'secure' => false,
+    
+    'same_site' => '',
+
+    'gc_probability' => [1, 1000],
+
+];

+ 23 - 0
config/static.php

@@ -0,0 +1,23 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+/**
+ * Static file settings
+ */
+return [
+    'enable' => true,
+    'middleware' => [     // Static file Middleware
+        //app\middleware\StaticFile::class,
+    ],
+];

+ 44 - 0
config/think-cache.php

@@ -0,0 +1,44 @@
+<?php
+return [
+    // 默认缓存驱动
+    'default' => 'redis',
+    // 缓存连接方式配置
+    'stores'  => [
+        // redis缓存
+        'redis' => [
+            // 驱动方式
+            'type' => 'redis',
+            // 服务器地址
+            'host' => '127.0.0.1',
+            // 无 ACL 用户请留空 username(Redis 6.0 起支持用户名 + 密码认证)
+            'username' => '',
+            // redis密码
+            'password' => '',
+            // 选择的数据库索引
+            'select' => 0,
+            // 缓存前缀
+            'prefix' => 'cache:',
+            // 默认缓存有效期 0表示永久缓存
+            'expire'     => 0,
+            // Thinkphp官方没有这个参数,由于生成的tag键默认不过期,如果tag键数量很大,避免长时间占用内存,可以设置一个超过其他缓存的过期时间,0为不设置
+            'tag_expire' => 86400 * 30,
+            // 缓存标签前缀
+            'tag_prefix' => 'tag:',
+            // 连接池配置
+            'pool' => [
+                'max_connections' => 5, // 最大连接数
+                'min_connections' => 1, // 最小连接数
+                'wait_timeout' => 3,    // 从连接池获取连接等待超时时间
+                'idle_timeout' => 60,   // 连接最大空闲时间,超过该时间会被回收
+                'heartbeat_interval' => 50, // 心跳检测间隔,需要小于60秒
+            ],
+        ],
+        // 文件缓存
+        'file' => [
+            // 驱动方式
+            'type' => 'file',
+            // 设置不同的缓存保存目录
+            'path' => runtime_path() . '/file/',
+        ],
+    ],
+];

+ 42 - 0
config/think-orm.php

@@ -0,0 +1,42 @@
+<?php
+
+return [
+    'default' => getenv('DB_DEFAULT'),
+    'connections' => [
+        'mysql' => [
+            // 数据库类型
+            'type' => 'mysql',
+            // 服务器地址
+            'hostname' => getenv('DB_HOST'),
+            // 数据库名
+            'database' => getenv('DB_NAME'),
+            // 数据库用户名
+            'username' => getenv('DB_USER'),
+            // 数据库密码
+            'password' => getenv('DB_PASSWORD'),
+            // 数据库连接端口
+            'hostport' => getenv('DB_PORT'),
+            // 数据库连接参数
+            'params' => [
+                // 连接超时3秒
+                \PDO::ATTR_TIMEOUT => 3,
+            ],
+            // 数据库编码默认采用utf8
+            'charset' => 'utf8',
+            // 数据库表前缀
+            'prefix' => '',
+            // 断线重连
+            'break_reconnect' => true,
+            // 连接池配置
+            'pool' => [
+                'max_connections' => 5, // 最大连接数
+                'min_connections' => 1, // 最小连接数
+                'wait_timeout' => 3,    // 从连接池获取连接等待超时时间
+                'idle_timeout' => 60,   // 连接最大空闲时间,超过该时间会被回收
+                'heartbeat_interval' => 50, // 心跳检测间隔,需要小于60秒
+            ],
+        ],
+    ],
+    // 自定义分页类
+    'paginator' =>  '',
+];

+ 25 - 0
config/translation.php

@@ -0,0 +1,25 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+/**
+ * Multilingual configuration
+ */
+return [
+    // Default language
+    'locale' => 'zh_CN',
+    // Fallback language
+    'fallback_locale' => ['zh_CN', 'en'],
+    // Folder where language files are stored
+    'path' => base_path() . '/resource/translations',
+];

+ 22 - 0
config/view.php

@@ -0,0 +1,22 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+use support\view\Raw;
+use support\view\Twig;
+use support\view\Blade;
+use support\view\ThinkPHP;
+
+return [
+    'handler' => Raw::class
+];

+ 11 - 0
docker-compose.yml

@@ -0,0 +1,11 @@
+version: "3"
+services:
+  webman:
+    build: .
+    container_name: docker-webman
+    restart: unless-stopped
+    volumes:
+      - "./:/app"
+    ports:
+      - "8787:8787"
+    command: ["php", "start.php", "start" ]

BIN
public/favicon.ico


+ 4 - 0
runtime/.gitignore

@@ -0,0 +1,4 @@
+*
+!logs
+!views
+!.gitignore

+ 2 - 0
runtime/logs/.gitignore

@@ -0,0 +1,2 @@
+*
+!.gitignore

+ 2 - 0
runtime/views/.gitignore

@@ -0,0 +1,2 @@
+*
+!.gitignore

+ 5 - 0
start.php

@@ -0,0 +1,5 @@
+#!/usr/bin/env php
+<?php
+chdir(__DIR__);
+require_once __DIR__ . '/vendor/autoload.php';
+support\App::run();

+ 24 - 0
support/Request.php

@@ -0,0 +1,24 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+namespace support;
+
+/**
+ * Class Request
+ * @package support
+ */
+class Request extends \Webman\Http\Request
+{
+
+}

+ 24 - 0
support/Response.php

@@ -0,0 +1,24 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+namespace support;
+
+/**
+ * Class Response
+ * @package support
+ */
+class Response extends \Webman\Http\Response
+{
+
+}

+ 1558 - 0
support/Setup.php

@@ -0,0 +1,1558 @@
+<?php
+
+declare(strict_types=1);
+
+namespace support;
+
+use Composer\Console\Application as ComposerApplication;
+use Composer\IO\IOInterface;
+use Composer\Script\Event;
+use Symfony\Component\Console\Cursor;
+use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Output\ConsoleOutput;
+use Symfony\Component\Console\Terminal;
+
+/**
+ * create-project setup wizard: interactive locale, timezone and optional components selection, then runs composer require.
+ */
+class Setup
+{
+    // --- Optional component package names ---
+
+    private const PACKAGE_CONSOLE           = 'webman/console';
+    private const PACKAGE_DATABASE          = 'webman/database';
+    private const PACKAGE_THINK_ORM         = 'webman/think-orm';
+    private const PACKAGE_REDIS             = 'webman/redis';
+    private const PACKAGE_ILLUMINATE_EVENTS = 'illuminate/events';
+    private const PACKAGE_ILLUMINATE_PAGINATION = 'illuminate/pagination';
+    private const PACKAGE_SYMFONY_VAR_DUMPER     = 'symfony/var-dumper';
+    private const PACKAGE_VALIDATION             = 'webman/validation';
+    private const PACKAGE_BLADE                  = 'webman/blade';
+    private const PACKAGE_TWIG                   = 'twig/twig';
+    private const PACKAGE_THINK_TEMPLATE         = 'topthink/think-template';
+
+    private const SETUP_TITLE = 'Webman Setup';
+
+    // --- Timezone regions ---
+
+    private const TIMEZONE_REGIONS = [
+        'Asia'       => \DateTimeZone::ASIA,
+        'Europe'     => \DateTimeZone::EUROPE,
+        'America'    => \DateTimeZone::AMERICA,
+        'Africa'     => \DateTimeZone::AFRICA,
+        'Australia'  => \DateTimeZone::AUSTRALIA,
+        'Pacific'    => \DateTimeZone::PACIFIC,
+        'Atlantic'   => \DateTimeZone::ATLANTIC,
+        'Indian'     => \DateTimeZone::INDIAN,
+        'Antarctica' => \DateTimeZone::ANTARCTICA,
+        'Arctic'     => \DateTimeZone::ARCTIC,
+        'UTC'        => \DateTimeZone::UTC,
+    ];
+
+    // --- Locale => default timezone ---
+
+    private const LOCALE_DEFAULT_TIMEZONES = [
+        'zh_CN' => 'Asia/Shanghai',
+        'zh_TW' => 'Asia/Taipei',
+        'en'    => 'UTC',
+        'ja'    => 'Asia/Tokyo',
+        'ko'    => 'Asia/Seoul',
+        'fr'    => 'Europe/Paris',
+        'de'    => 'Europe/Berlin',
+        'es'    => 'Europe/Madrid',
+        'pt_BR' => 'America/Sao_Paulo',
+        'ru'    => 'Europe/Moscow',
+        'vi'    => 'Asia/Ho_Chi_Minh',
+        'tr'    => 'Europe/Istanbul',
+        'id'    => 'Asia/Jakarta',
+        'th'    => 'Asia/Bangkok',
+    ];
+
+    // --- Locale options (localized display names) ---
+
+    private const LOCALE_LABELS = [
+        'zh_CN' => '简体中文',
+        'zh_TW' => '繁體中文',
+        'en'    => 'English',
+        'ja'    => '日本語',
+        'ko'    => '한국어',
+        'fr'    => 'Français',
+        'de'    => 'Deutsch',
+        'es'    => 'Español',
+        'pt_BR' => 'Português (Brasil)',
+        'ru'    => 'Русский',
+        'vi'    => 'Tiếng Việt',
+        'tr'    => 'Türkçe',
+        'id'    => 'Bahasa Indonesia',
+        'th'    => 'ไทย',
+    ];
+
+    // --- Multilingual messages (%s = placeholder) ---
+
+    private const MESSAGES = [
+        'zh_CN' => [
+            'remove_package_question' => '发现以下已安装组件本次未选择,是否将其卸载 ?%s',
+            'removing_package'   => '- 准备移除组件 %s',
+            'removing'           => '卸载:',
+            'error_remove'       => '卸载组件出错,请手动执行:composer remove %s',
+            'done_remove'        => '已卸载组件。',
+                        'skip'             => '非交互模式,跳过安装向导。',
+            'default_choice'   => ' (默认 %s)',
+            'timezone_prompt'  => '时区 (默认 %s,输入可联想补全): ',
+            'timezone_title'   => '时区设置 (默认 %s)',
+            'timezone_help'    => '输入关键字Tab自动补全,可↑↓下选择:',
+            'timezone_region'  => '选择时区区域',
+            'timezone_city'    => '选择时区',
+            'timezone_invalid' => '无效的时区,已使用默认值 %s',
+            'timezone_input_prompt'  => '输入时区或关键字:',
+            'timezone_pick_prompt'   => '请输入数字编号或关键字:',
+            'timezone_no_match'      => '未找到匹配的时区,请重试。',
+            'timezone_invalid_index' => '无效的编号,请重新输入。',
+            'yes'              => '是',
+            'no'               => '否',
+            'adding_package'   => '- 添加依赖 %s',
+            'console_question' => '安装命令行组件 webman/console',
+            'db_question'      => '数据库组件',
+            'db_none'          => '不安装',
+            'db_invalid'       => '请输入有效选项',
+            'redis_question'       => '安装 Redis 组件 webman/redis',
+            'events_note'          => '  (Redis 依赖 illuminate/events,已自动包含)',
+            'validation_question'  => '安装验证器组件 webman/validation',
+            'template_question'    => '模板引擎',
+            'template_none'        => '不安装',
+            'no_components'        => '未选择额外组件。',
+            'installing'           => '即将安装:',
+            'running'              => '执行:',
+            'error_install'        => '安装可选组件时出错,请手动执行:composer require %s',
+            'done'                 => '可选组件安装完成。',
+            'summary_locale'       => '语言:%s',
+            'summary_timezone'     => '时区:%s',
+        ],
+        'zh_TW' => [
+            'skip'             => '非交互模式,跳過安裝嚮導。',
+            'default_choice'   => ' (預設 %s)',
+            'timezone_prompt'  => '時區 (預設 %s,輸入可聯想補全): ',
+            'timezone_title'   => '時區設定 (預設 %s)',
+            'timezone_help'    => '輸入關鍵字Tab自動補全,可↑↓上下選擇:',
+            'timezone_region'  => '選擇時區區域',
+            'timezone_city'    => '選擇時區',
+            'timezone_invalid' => '無效的時區,已使用預設值 %s',
+            'timezone_input_prompt'  => '輸入時區或關鍵字:',
+            'timezone_pick_prompt'   => '請輸入數字編號或關鍵字:',
+            'timezone_no_match'      => '未找到匹配的時區,請重試。',
+            'timezone_invalid_index' => '無效的編號,請重新輸入。',
+            'yes'              => '是',
+            'no'               => '否',
+            'adding_package'   => '- 新增依賴 %s',
+            'console_question' => '安裝命令列組件 webman/console',
+            'db_question'      => '資料庫組件',
+            'db_none'          => '不安裝',
+            'db_invalid'       => '請輸入有效選項',
+            'redis_question'       => '安裝 Redis 組件 webman/redis',
+            'events_note'          => '  (Redis 依賴 illuminate/events,已自動包含)',
+            'validation_question'  => '安裝驗證器組件 webman/validation',
+            'template_question'    => '模板引擎',
+            'template_none'        => '不安裝',
+            'no_components'        => '未選擇額外組件。',
+            'installing'           => '即將安裝:',
+            'running'              => '執行:',
+            'error_install'        => '安裝可選組件時出錯,請手動執行:composer require %s',
+            'done'                 => '可選組件安裝完成。',
+            'summary_locale'       => '語言:%s',
+            'summary_timezone'     => '時區:%s',
+        ],
+        'en' => [
+            'skip'             => 'Non-interactive mode, skipping setup wizard.',
+            'default_choice'   => ' (default %s)',
+            'timezone_prompt'  => 'Timezone (default=%s, type to autocomplete): ',
+            'timezone_title'   => 'Timezone (default=%s)',
+            'timezone_help'    => 'Type keyword then press Tab to autocomplete, use ↑↓ to choose:',
+            'timezone_region'  => 'Select timezone region',
+            'timezone_city'    => 'Select timezone',
+            'timezone_invalid' => 'Invalid timezone, using default %s',
+            'timezone_input_prompt'  => 'Enter timezone or keyword:',
+            'timezone_pick_prompt'   => 'Enter number or keyword:',
+            'timezone_no_match'      => 'No matching timezone found, please try again.',
+            'timezone_invalid_index' => 'Invalid number, please try again.',
+            'yes'              => 'yes',
+            'no'               => 'no',
+            'adding_package'   => '- Adding package %s',
+            'console_question' => 'Install console component webman/console',
+            'db_question'      => 'Database component',
+            'db_none'          => 'None',
+            'db_invalid'       => 'Please enter a valid option',
+            'redis_question'       => 'Install Redis component webman/redis',
+            'events_note'          => '  (Redis requires illuminate/events, automatically included)',
+            'validation_question'  => 'Install validator component webman/validation',
+            'template_question'    => 'Template engine',
+            'template_none'        => 'None',
+            'no_components'        => 'No optional components selected.',
+            'installing'           => 'Installing:',
+            'running'              => 'Running:',
+            'error_install'        => 'Failed to install. Try manually: composer require %s',
+            'done'                 => 'Optional components installed.',
+            'summary_locale'       => 'Language: %s',
+            'summary_timezone'     => 'Timezone: %s',
+        ],
+        'ja' => [
+            'skip'             => '非対話モードのため、セットアップウィザードをスキップします。',
+            'default_choice'   => ' (デフォルト %s)',
+            'timezone_prompt'  => 'タイムゾーン (デフォルト=%s、入力で補完): ',
+            'timezone_title'   => 'タイムゾーン (デフォルト=%s)',
+            'timezone_help'    => 'キーワード入力→Tabで補完、↑↓で選択:',
+            'timezone_region'  => 'タイムゾーンの地域を選択',
+            'timezone_city'    => 'タイムゾーンを選択',
+            'timezone_invalid' => '無効なタイムゾーンです。デフォルト %s を使用します',
+            'timezone_input_prompt'  => 'タイムゾーンまたはキーワードを入力:',
+            'timezone_pick_prompt'   => '番号またはキーワードを入力:',
+            'timezone_no_match'      => '一致するタイムゾーンが見つかりません。再試行してください。',
+            'timezone_invalid_index' => '無効な番号です。もう一度入力してください。',
+            'yes'              => 'はい',
+            'no'               => 'いいえ',
+            'adding_package'   => '- パッケージを追加 %s',
+            'console_question' => 'コンソールコンポーネント webman/console をインストール',
+            'db_question'      => 'データベースコンポーネント',
+            'db_none'          => 'インストールしない',
+            'db_invalid'       => '有効なオプションを入力してください',
+            'redis_question'       => 'Redis コンポーネント webman/redis をインストール',
+            'events_note'          => '  (Redis は illuminate/events が必要です。自動的に含まれます)',
+            'validation_question'  => 'バリデーションコンポーネント webman/validation をインストール',
+            'template_question'    => 'テンプレートエンジン',
+            'template_none'        => 'インストールしない',
+            'no_components'        => 'オプションコンポーネントが選択されていません。',
+            'installing'           => 'インストール中:',
+            'running'              => '実行中:',
+            'error_install'        => 'インストールに失敗しました。手動で実行してください:composer require %s',
+            'done'                 => 'オプションコンポーネントのインストールが完了しました。',
+            'summary_locale'       => '言語:%s',
+            'summary_timezone'     => 'タイムゾーン:%s',
+        ],
+        'ko' => [
+            'skip'             => '비대화형 모드입니다. 설치 마법사를 건너뜁니다.',
+            'default_choice'   => ' (기본값 %s)',
+            'timezone_prompt'  => '시간대 (기본값=%s, 입력하여 자동완성): ',
+            'timezone_title'   => '시간대 (기본값=%s)',
+            'timezone_help'    => '키워드 입력 후 Tab 자동완성, ↑↓로 선택:',
+            'timezone_region'  => '시간대 지역 선택',
+            'timezone_city'    => '시간대 선택',
+            'timezone_invalid' => '잘못된 시간대입니다. 기본값 %s 을(를) 사용합니다',
+            'timezone_input_prompt'  => '시간대 또는 키워드 입력:',
+            'timezone_pick_prompt'   => '번호 또는 키워드 입력:',
+            'timezone_no_match'      => '일치하는 시간대를 찾을 수 없습니다. 다시 시도하세요.',
+            'timezone_invalid_index' => '잘못된 번호입니다. 다시 입력하세요.',
+            'yes'              => '예',
+            'no'               => '아니오',
+            'adding_package'   => '- 패키지 추가 %s',
+            'console_question' => '콘솔 컴포넌트 webman/console 설치',
+            'db_question'      => '데이터베이스 컴포넌트',
+            'db_none'          => '설치 안 함',
+            'db_invalid'       => '유효한 옵션을 입력하세요',
+            'redis_question'       => 'Redis 컴포넌트 webman/redis 설치',
+            'events_note'          => '  (Redis는 illuminate/events가 필요합니다. 자동으로 포함됩니다)',
+            'validation_question'  => '검증 컴포넌트 webman/validation 설치',
+            'template_question'    => '템플릿 엔진',
+            'template_none'        => '설치 안 함',
+            'no_components'        => '선택된 추가 컴포넌트가 없습니다.',
+            'installing'           => '설치 예정:',
+            'running'              => '실행 중:',
+            'error_install'        => '설치에 실패했습니다. 수동으로 실행하세요: composer require %s',
+            'done'                 => '선택 컴포넌트 설치가 완료되었습니다.',
+            'summary_locale'       => '언어: %s',
+            'summary_timezone'     => '시간대: %s',
+        ],
+        'fr' => [
+            'skip'             => 'Mode non interactif, assistant d\'installation ignoré.',
+            'default_choice'   => ' (défaut %s)',
+            'timezone_prompt'  => 'Fuseau horaire (défaut=%s, tapez pour compléter) : ',
+            'timezone_title'   => 'Fuseau horaire (défaut=%s)',
+            'timezone_help'    => 'Tapez un mot-clé, Tab pour compléter, ↑↓ pour choisir :',
+            'timezone_region'  => 'Sélectionnez la région du fuseau horaire',
+            'timezone_city'    => 'Sélectionnez le fuseau horaire',
+            'timezone_invalid' => 'Fuseau horaire invalide, utilisation de %s par défaut',
+            'timezone_input_prompt'  => 'Entrez un fuseau horaire ou un mot-clé :',
+            'timezone_pick_prompt'   => 'Entrez un numéro ou un mot-clé :',
+            'timezone_no_match'      => 'Aucun fuseau horaire correspondant, veuillez réessayer.',
+            'timezone_invalid_index' => 'Numéro invalide, veuillez réessayer.',
+            'yes'              => 'oui',
+            'no'               => 'non',
+            'adding_package'   => '- Ajout du paquet %s',
+            'console_question' => 'Installer le composant console webman/console',
+            'db_question'      => 'Composant base de données',
+            'db_none'          => 'Aucun',
+            'db_invalid'       => 'Veuillez entrer une option valide',
+            'redis_question'       => 'Installer le composant Redis webman/redis',
+            'events_note'          => '  (Redis nécessite illuminate/events, inclus automatiquement)',
+            'validation_question'  => 'Installer le composant de validation webman/validation',
+            'template_question'    => 'Moteur de templates',
+            'template_none'        => 'Aucun',
+            'no_components'        => 'Aucun composant optionnel sélectionné.',
+            'installing'           => 'Installation en cours :',
+            'running'              => 'Exécution :',
+            'error_install'        => 'Échec de l\'installation. Essayez manuellement : composer require %s',
+            'done'                 => 'Composants optionnels installés.',
+            'summary_locale'       => 'Langue : %s',
+            'summary_timezone'     => 'Fuseau horaire : %s',
+        ],
+        'de' => [
+            'skip'             => 'Nicht-interaktiver Modus, Einrichtungsassistent übersprungen.',
+            'default_choice'   => ' (Standard %s)',
+            'timezone_prompt'  => 'Zeitzone (Standard=%s, Eingabe zur Vervollständigung): ',
+            'timezone_title'   => 'Zeitzone (Standard=%s)',
+            'timezone_help'    => 'Stichwort tippen, Tab ergänzt, ↑↓ auswählen:',
+            'timezone_region'  => 'Zeitzone Region auswählen',
+            'timezone_city'    => 'Zeitzone auswählen',
+            'timezone_invalid' => 'Ungültige Zeitzone, Standardwert %s wird verwendet',
+            'timezone_input_prompt'  => 'Zeitzone oder Stichwort eingeben:',
+            'timezone_pick_prompt'   => 'Nummer oder Stichwort eingeben:',
+            'timezone_no_match'      => 'Keine passende Zeitzone gefunden, bitte erneut versuchen.',
+            'timezone_invalid_index' => 'Ungültige Nummer, bitte erneut eingeben.',
+            'yes'              => 'ja',
+            'no'               => 'nein',
+            'adding_package'   => '- Paket hinzufügen %s',
+            'console_question' => 'Konsolen-Komponente webman/console installieren',
+            'db_question'      => 'Datenbank-Komponente',
+            'db_none'          => 'Keine',
+            'db_invalid'       => 'Bitte geben Sie eine gültige Option ein',
+            'redis_question'       => 'Redis-Komponente webman/redis installieren',
+            'events_note'          => '  (Redis benötigt illuminate/events, automatisch eingeschlossen)',
+            'validation_question'  => 'Validierungs-Komponente webman/validation installieren',
+            'template_question'    => 'Template-Engine',
+            'template_none'        => 'Keine',
+            'no_components'        => 'Keine optionalen Komponenten ausgewählt.',
+            'installing'           => 'Installation:',
+            'running'              => 'Ausführung:',
+            'error_install'        => 'Installation fehlgeschlagen. Manuell ausführen: composer require %s',
+            'done'                 => 'Optionale Komponenten installiert.',
+            'summary_locale'       => 'Sprache: %s',
+            'summary_timezone'     => 'Zeitzone: %s',
+        ],
+        'es' => [
+            'skip'             => 'Modo no interactivo, asistente de instalación omitido.',
+            'default_choice'   => ' (predeterminado %s)',
+            'timezone_prompt'  => 'Zona horaria (predeterminado=%s, escriba para autocompletar): ',
+            'timezone_title'   => 'Zona horaria (predeterminado=%s)',
+            'timezone_help'    => 'Escriba una palabra clave, Tab autocompleta, use ↑↓ para elegir:',
+            'timezone_region'  => 'Seleccione la región de zona horaria',
+            'timezone_city'    => 'Seleccione la zona horaria',
+            'timezone_invalid' => 'Zona horaria inválida, usando valor predeterminado %s',
+            'timezone_input_prompt'  => 'Ingrese zona horaria o palabra clave:',
+            'timezone_pick_prompt'   => 'Ingrese número o palabra clave:',
+            'timezone_no_match'      => 'No se encontró zona horaria coincidente, intente de nuevo.',
+            'timezone_invalid_index' => 'Número inválido, intente de nuevo.',
+            'yes'              => 'sí',
+            'no'               => 'no',
+            'adding_package'   => '- Agregando paquete %s',
+            'console_question' => 'Instalar componente de consola webman/console',
+            'db_question'      => 'Componente de base de datos',
+            'db_none'          => 'Ninguno',
+            'db_invalid'       => 'Por favor ingrese una opción válida',
+            'redis_question'       => 'Instalar componente Redis webman/redis',
+            'events_note'          => '  (Redis requiere illuminate/events, incluido automáticamente)',
+            'validation_question'  => 'Instalar componente de validación webman/validation',
+            'template_question'    => 'Motor de plantillas',
+            'template_none'        => 'Ninguno',
+            'no_components'        => 'No se seleccionaron componentes opcionales.',
+            'installing'           => 'Instalando:',
+            'running'              => 'Ejecutando:',
+            'error_install'        => 'Error en la instalación. Intente manualmente: composer require %s',
+            'done'                 => 'Componentes opcionales instalados.',
+            'summary_locale'       => 'Idioma: %s',
+            'summary_timezone'     => 'Zona horaria: %s',
+        ],
+        'pt_BR' => [
+            'skip'             => 'Modo não interativo, assistente de instalação ignorado.',
+            'default_choice'   => ' (padrão %s)',
+            'timezone_prompt'  => 'Fuso horário (padrão=%s, digite para autocompletar): ',
+            'timezone_title'   => 'Fuso horário (padrão=%s)',
+            'timezone_help'    => 'Digite uma palavra-chave, Tab autocompleta, use ↑↓ para escolher:',
+            'timezone_region'  => 'Selecione a região do fuso horário',
+            'timezone_city'    => 'Selecione o fuso horário',
+            'timezone_invalid' => 'Fuso horário inválido, usando padrão %s',
+            'timezone_input_prompt'  => 'Digite fuso horário ou palavra-chave:',
+            'timezone_pick_prompt'   => 'Digite número ou palavra-chave:',
+            'timezone_no_match'      => 'Nenhum fuso horário encontrado, tente novamente.',
+            'timezone_invalid_index' => 'Número inválido, tente novamente.',
+            'yes'              => 'sim',
+            'no'               => 'não',
+            'adding_package'   => '- Adicionando pacote %s',
+            'console_question' => 'Instalar componente de console webman/console',
+            'db_question'      => 'Componente de banco de dados',
+            'db_none'          => 'Nenhum',
+            'db_invalid'       => 'Por favor, digite uma opção válida',
+            'redis_question'       => 'Instalar componente Redis webman/redis',
+            'events_note'          => '  (Redis requer illuminate/events, incluído automaticamente)',
+            'validation_question'  => 'Instalar componente de validação webman/validation',
+            'template_question'    => 'Motor de templates',
+            'template_none'        => 'Nenhum',
+            'no_components'        => 'Nenhum componente opcional selecionado.',
+            'installing'           => 'Instalando:',
+            'running'              => 'Executando:',
+            'error_install'        => 'Falha na instalação. Tente manualmente: composer require %s',
+            'done'                 => 'Componentes opcionais instalados.',
+            'summary_locale'       => 'Idioma: %s',
+            'summary_timezone'     => 'Fuso horário: %s',
+        ],
+        'ru' => [
+            'skip'             => 'Неинтерактивный режим, мастер установки пропущен.',
+            'default_choice'   => ' (по умолчанию %s)',
+            'timezone_prompt'  => 'Часовой пояс (по умолчанию=%s, введите для автодополнения): ',
+            'timezone_title'   => 'Часовой пояс (по умолчанию=%s)',
+            'timezone_help'    => 'Введите ключевое слово, Tab для автодополнения, ↑↓ для выбора:',
+            'timezone_region'  => 'Выберите регион часового пояса',
+            'timezone_city'    => 'Выберите часовой пояс',
+            'timezone_invalid' => 'Неверный часовой пояс, используется значение по умолчанию %s',
+            'timezone_input_prompt'  => 'Введите часовой пояс или ключевое слово:',
+            'timezone_pick_prompt'   => 'Введите номер или ключевое слово:',
+            'timezone_no_match'      => 'Совпадающий часовой пояс не найден, попробуйте снова.',
+            'timezone_invalid_index' => 'Неверный номер, попробуйте снова.',
+            'yes'              => 'да',
+            'no'               => 'нет',
+            'adding_package'   => '- Добавление пакета %s',
+            'console_question' => 'Установить консольный компонент webman/console',
+            'db_question'      => 'Компонент базы данных',
+            'db_none'          => 'Не устанавливать',
+            'db_invalid'       => 'Пожалуйста, введите допустимый вариант',
+            'redis_question'       => 'Установить компонент Redis webman/redis',
+            'events_note'          => '  (Redis требует illuminate/events, автоматически включён)',
+            'validation_question'  => 'Установить компонент валидации webman/validation',
+            'template_question'    => 'Шаблонизатор',
+            'template_none'        => 'Не устанавливать',
+            'no_components'        => 'Дополнительные компоненты не выбраны.',
+            'installing'           => 'Установка:',
+            'running'              => 'Выполнение:',
+            'error_install'        => 'Ошибка установки. Выполните вручную: composer require %s',
+            'done'                 => 'Дополнительные компоненты установлены.',
+            'summary_locale'       => 'Язык: %s',
+            'summary_timezone'     => 'Часовой пояс: %s',
+        ],
+        'vi' => [
+            'skip'             => 'Chế độ không tương tác, bỏ qua trình hướng dẫn cài đặt.',
+            'default_choice'   => ' (mặc định %s)',
+            'timezone_prompt'  => 'Múi giờ (mặc định=%s, nhập để tự động hoàn thành): ',
+            'timezone_title'   => 'Múi giờ (mặc định=%s)',
+            'timezone_help'    => 'Nhập từ khóa, Tab để tự hoàn thành, dùng ↑↓ để chọn:',
+            'timezone_region'  => 'Chọn khu vực múi giờ',
+            'timezone_city'    => 'Chọn múi giờ',
+            'timezone_invalid' => 'Múi giờ không hợp lệ, sử dụng mặc định %s',
+            'timezone_input_prompt'  => 'Nhập múi giờ hoặc từ khóa:',
+            'timezone_pick_prompt'   => 'Nhập số thứ tự hoặc từ khóa:',
+            'timezone_no_match'      => 'Không tìm thấy múi giờ phù hợp, vui lòng thử lại.',
+            'timezone_invalid_index' => 'Số không hợp lệ, vui lòng thử lại.',
+            'yes'              => 'có',
+            'no'               => 'không',
+            'adding_package'   => '- Thêm gói %s',
+            'console_question' => 'Cài đặt thành phần console webman/console',
+            'db_question'      => 'Thành phần cơ sở dữ liệu',
+            'db_none'          => 'Không cài đặt',
+            'db_invalid'       => 'Vui lòng nhập tùy chọn hợp lệ',
+            'redis_question'       => 'Cài đặt thành phần Redis webman/redis',
+            'events_note'          => '  (Redis cần illuminate/events, đã tự động bao gồm)',
+            'validation_question'  => 'Cài đặt thành phần xác thực webman/validation',
+            'template_question'    => 'Công cụ mẫu',
+            'template_none'        => 'Không cài đặt',
+            'no_components'        => 'Không có thành phần tùy chọn nào được chọn.',
+            'installing'           => 'Đang cài đặt:',
+            'running'              => 'Đang thực thi:',
+            'error_install'        => 'Cài đặt thất bại. Thử thủ công: composer require %s',
+            'done'                 => 'Các thành phần tùy chọn đã được cài đặt.',
+            'summary_locale'       => 'Ngôn ngữ: %s',
+            'summary_timezone'     => 'Múi giờ: %s',
+        ],
+        'tr' => [
+            'skip'             => 'Etkileşimsiz mod, kurulum sihirbazı atlanıyor.',
+            'default_choice'   => ' (varsayılan %s)',
+            'timezone_prompt'  => 'Saat dilimi (varsayılan=%s, otomatik tamamlama için yazın): ',
+            'timezone_title'   => 'Saat dilimi (varsayılan=%s)',
+            'timezone_help'    => 'Anahtar kelime yazın, Tab tamamlar, ↑↓ ile seçin:',
+            'timezone_region'  => 'Saat dilimi bölgesini seçin',
+            'timezone_city'    => 'Saat dilimini seçin',
+            'timezone_invalid' => 'Geçersiz saat dilimi, varsayılan %s kullanılıyor',
+            'timezone_input_prompt'  => 'Saat dilimi veya anahtar kelime girin:',
+            'timezone_pick_prompt'   => 'Numara veya anahtar kelime girin:',
+            'timezone_no_match'      => 'Eşleşen saat dilimi bulunamadı, tekrar deneyin.',
+            'timezone_invalid_index' => 'Geçersiz numara, tekrar deneyin.',
+            'yes'              => 'evet',
+            'no'               => 'hayır',
+            'adding_package'   => '- Paket ekleniyor %s',
+            'console_question' => 'Konsol bileşeni webman/console yüklensin mi',
+            'db_question'      => 'Veritabanı bileşeni',
+            'db_none'          => 'Yok',
+            'db_invalid'       => 'Lütfen geçerli bir seçenek girin',
+            'redis_question'       => 'Redis bileşeni webman/redis yüklensin mi',
+            'events_note'          => '  (Redis, illuminate/events gerektirir, otomatik olarak dahil edildi)',
+            'validation_question'  => 'Doğrulama bileşeni webman/validation yüklensin mi',
+            'template_question'    => 'Şablon motoru',
+            'template_none'        => 'Yok',
+            'no_components'        => 'İsteğe bağlı bileşen seçilmedi.',
+            'installing'           => 'Yükleniyor:',
+            'running'              => 'Çalıştırılıyor:',
+            'error_install'        => 'Yükleme başarısız. Manuel olarak deneyin: composer require %s',
+            'done'                 => 'İsteğe bağlı bileşenler yüklendi.',
+            'summary_locale'       => 'Dil: %s',
+            'summary_timezone'     => 'Saat dilimi: %s',
+        ],
+        'id' => [
+            'skip'             => 'Mode non-interaktif, melewati wizard instalasi.',
+            'default_choice'   => ' (default %s)',
+            'timezone_prompt'  => 'Zona waktu (default=%s, ketik untuk melengkapi): ',
+            'timezone_title'   => 'Zona waktu (default=%s)',
+            'timezone_help'    => 'Ketik kata kunci, Tab untuk melengkapi, gunakan ↑↓ untuk memilih:',
+            'timezone_region'  => 'Pilih wilayah zona waktu',
+            'timezone_city'    => 'Pilih zona waktu',
+            'timezone_invalid' => 'Zona waktu tidak valid, menggunakan default %s',
+            'timezone_input_prompt'  => 'Masukkan zona waktu atau kata kunci:',
+            'timezone_pick_prompt'   => 'Masukkan nomor atau kata kunci:',
+            'timezone_no_match'      => 'Zona waktu tidak ditemukan, silakan coba lagi.',
+            'timezone_invalid_index' => 'Nomor tidak valid, silakan coba lagi.',
+            'yes'              => 'ya',
+            'no'               => 'tidak',
+            'adding_package'   => '- Menambahkan paket %s',
+            'console_question' => 'Instal komponen konsol webman/console',
+            'db_question'      => 'Komponen database',
+            'db_none'          => 'Tidak ada',
+            'db_invalid'       => 'Silakan masukkan opsi yang valid',
+            'redis_question'       => 'Instal komponen Redis webman/redis',
+            'events_note'          => '  (Redis memerlukan illuminate/events, otomatis disertakan)',
+            'validation_question'  => 'Instal komponen validasi webman/validation',
+            'template_question'    => 'Mesin template',
+            'template_none'        => 'Tidak ada',
+            'no_components'        => 'Tidak ada komponen opsional yang dipilih.',
+            'installing'           => 'Menginstal:',
+            'running'              => 'Menjalankan:',
+            'error_install'        => 'Instalasi gagal. Coba manual: composer require %s',
+            'done'                 => 'Komponen opsional terinstal.',
+            'summary_locale'       => 'Bahasa: %s',
+            'summary_timezone'     => 'Zona waktu: %s',
+        ],
+        'th' => [
+            'skip'             => 'โหมดไม่โต้ตอบ ข้ามตัวช่วยติดตั้ง',
+            'default_choice'   => ' (ค่าเริ่มต้น %s)',
+            'timezone_prompt'  => 'เขตเวลา (ค่าเริ่มต้น=%s พิมพ์เพื่อเติมอัตโนมัติ): ',
+            'timezone_title'   => 'เขตเวลา (ค่าเริ่มต้น=%s)',
+            'timezone_help'    => 'พิมพ์คีย์เวิร์ดแล้วกด Tab เพื่อเติมอัตโนมัติ ใช้ ↑↓ เพื่อเลือก:',
+            'timezone_region'  => 'เลือกภูมิภาคเขตเวลา',
+            'timezone_city'    => 'เลือกเขตเวลา',
+            'timezone_invalid' => 'เขตเวลาไม่ถูกต้อง ใช้ค่าเริ่มต้น %s',
+            'timezone_input_prompt'  => 'ป้อนเขตเวลาหรือคำค้น:',
+            'timezone_pick_prompt'   => 'ป้อนหมายเลขหรือคำค้น:',
+            'timezone_no_match'      => 'ไม่พบเขตเวลาที่ตรงกัน กรุณาลองอีกครั้ง',
+            'timezone_invalid_index' => 'หมายเลขไม่ถูกต้อง กรุณาลองอีกครั้ง',
+            'yes'              => 'ใช่',
+            'no'               => 'ไม่',
+            'adding_package'   => '- เพิ่มแพ็กเกจ %s',
+            'console_question' => 'ติดตั้งคอมโพเนนต์คอนโซล webman/console',
+            'db_question'      => 'คอมโพเนนต์ฐานข้อมูล',
+            'db_none'          => 'ไม่ติดตั้ง',
+            'db_invalid'       => 'กรุณาป้อนตัวเลือกที่ถูกต้อง',
+            'redis_question'       => 'ติดตั้งคอมโพเนนต์ Redis webman/redis',
+            'events_note'          => '  (Redis ต้องการ illuminate/events รวมไว้โดยอัตโนมัติ)',
+            'validation_question'  => 'ติดตั้งคอมโพเนนต์ตรวจสอบ webman/validation',
+            'template_question'    => 'เทมเพลตเอนจิน',
+            'template_none'        => 'ไม่ติดตั้ง',
+            'no_components'        => 'ไม่ได้เลือกคอมโพเนนต์เสริม',
+            'installing'           => 'กำลังติดตั้ง:',
+            'running'              => 'กำลังดำเนินการ:',
+            'error_install'        => 'ติดตั้งล้มเหลว ลองด้วยตนเอง: composer require %s',
+            'done'                 => 'คอมโพเนนต์เสริมติดตั้งเรียบร้อยแล้ว',
+            'summary_locale'       => 'ภาษา: %s',
+            'summary_timezone'     => 'เขตเวลา: %s',
+        ],
+    ];
+
+    // --- Interrupt message (Ctrl+C) ---
+
+    private const INTERRUPTED_MESSAGES = [
+        'zh_CN' => '安装中断,可运行 composer setup-webman 可重新设置。',
+        'zh_TW' => '安裝中斷,可運行 composer setup-webman 重新設置。',
+        'en'    => 'Setup interrupted. Run "composer setup-webman" to restart setup.',
+        'ja'    => 'セットアップが中断されました。composer setup-webman を実行して再設定できます。',
+        'ko'    => '설치가 중단되었습니다. composer setup-webman 을 실행하여 다시 설정할 수 있습니다.',
+        'fr'    => 'Installation interrompue. Exécutez « composer setup-webman » pour recommencer.',
+        'de'    => 'Einrichtung abgebrochen. Führen Sie "composer setup-webman" aus, um neu zu starten.',
+        'es'    => 'Instalación interrumpida. Ejecute "composer setup-webman" para reiniciar.',
+        'pt_BR' => 'Instalação interrompida. Execute "composer setup-webman" para reiniciar.',
+        'ru'    => 'Установка прервана. Выполните «composer setup-webman» для повторной настройки.',
+        'vi'    => 'Cài đặt bị gián đoạn. Chạy "composer setup-webman" để cài đặt lại.',
+        'tr'    => 'Kurulum kesildi. Yeniden kurmak için "composer setup-webman" komutunu çalıştırın.',
+        'id'    => 'Instalasi terganggu. Jalankan "composer setup-webman" untuk mengatur ulang.',
+        'th'    => 'การติดตั้งถูกขัดจังหวะ เรียกใช้ "composer setup-webman" เพื่อตั้งค่าใหม่',
+    ];
+
+    // --- Signal handling state ---
+
+    /** @var string|null Saved stty mode for terminal restoration on interrupt */
+    private static ?string $sttyMode = null;
+
+    /** @var string Current locale for interrupt message */
+    private static string $interruptLocale = 'en';
+
+    // ═══════════════════════════════════════════════════════════════
+    // Entry
+    // ═══════════════════════════════════════════════════════════════
+
+    public static function run(Event $event): void
+    {
+        $io = $event->getIO();
+
+        // Non-interactive mode: use English for skip message
+        if (!$io->isInteractive()) {
+            $io->write('<comment>' . self::MESSAGES['en']['skip'] . '</comment>');
+            return;
+        }
+
+        try {
+            self::doRun($event, $io);
+        } catch (\Throwable $e) {
+            $io->writeError('');
+            $io->writeError('<error>Setup wizard error: ' . $e->getMessage() . '</error>');
+            $io->writeError('<comment>Run "composer setup-webman" to retry.</comment>');
+        }
+    }
+
+    private static function doRun(Event $event, IOInterface $io): void
+    {
+        $io->write('');
+
+        // Register Ctrl+C handler
+        self::registerInterruptHandler();
+
+        // Banner title (must be before locale selection)
+        self::renderTitle();
+
+        // 1. Locale selection
+        $locale = self::askLocale($io);
+        self::$interruptLocale = $locale;
+        $defaultTimezone = self::LOCALE_DEFAULT_TIMEZONES[$locale] ?? 'UTC';
+        $msg = fn(string $key, string ...$args): string =>
+        empty($args) ? self::MESSAGES[$locale][$key] : sprintf(self::MESSAGES[$locale][$key], ...$args);
+
+        // Write locale config (update when not default)
+        if ($locale !== 'zh_CN') {
+            self::updateConfig($event, 'config/translation.php', "'locale'", $locale);
+        }
+
+        $io->write('');
+        $io->write('');
+
+        // 2. Timezone selection (default by locale)
+        $timezone = self::askTimezone($io, $msg, $defaultTimezone);
+        if ($timezone !== 'Asia/Shanghai') {
+            self::updateConfig($event, 'config/app.php', "'default_timezone'", $timezone);
+        }
+
+        // 3. Optional components
+        $packages = self::askComponents($io, $msg);
+
+        // 4. Remove unselected components
+        $removePackages = self::askRemoveComponents($event, $packages, $io, $msg);
+
+        // 5. Summary
+        $io->write('');
+        $io->write('─────────────────────────────────────');
+        $io->write('<info>' . $msg('summary_locale', self::LOCALE_LABELS[$locale]) . '</info>');
+        $io->write('<info>' . $msg('summary_timezone', $timezone) . '</info>');
+
+        // Remove unselected packages first to avoid dependency conflicts
+        if ($removePackages !== []) {
+            $io->write('');
+            $io->write('<info>' . $msg('removing') . '</info>');
+
+            $secondaryPackages = [
+                self::PACKAGE_ILLUMINATE_EVENTS,
+                self::PACKAGE_ILLUMINATE_PAGINATION,
+                self::PACKAGE_SYMFONY_VAR_DUMPER,
+            ];
+            $displayRemovePackages = array_diff($removePackages, $secondaryPackages);
+            foreach ($displayRemovePackages as $pkg) {
+                $io->write('  - ' . $pkg);
+            }
+            $io->write('');
+            self::runComposerRemove($removePackages, $io, $msg);
+        }
+
+        // Then install selected packages
+        if ($packages !== []) {
+            $io->write('');
+            $io->write('<info>' . $msg('installing') . '</info> ' . implode(', ', $packages));
+            $io->write('');
+            self::runComposerRequire($packages, $io, $msg);
+        } elseif ($removePackages === []) {
+            $io->write('<info>' . $msg('no_components') . '</info>');
+        }
+    }
+
+    private static function renderTitle(): void
+    {
+        $output = new ConsoleOutput();
+        $terminalWidth = (new Terminal())->getWidth();
+        if ($terminalWidth <= 0) {
+            $terminalWidth = 80;
+        }
+
+        $text = ' ' . self::SETUP_TITLE . ' ';
+        $minBoxWidth = 44;
+        $maxBoxWidth = min($terminalWidth, 96);
+        $boxWidth = min($maxBoxWidth, max($minBoxWidth, mb_strwidth($text) + 10));
+
+        $innerWidth = $boxWidth - 2;
+        $textWidth = mb_strwidth($text);
+        $pad = max(0, $innerWidth - $textWidth);
+        $left = intdiv($pad, 2);
+        $right = $pad - $left;
+        $line2 = '│' . str_repeat(' ', $left) . $text . str_repeat(' ', $right) . '│';
+        $line1 = '┌' . str_repeat('─', $innerWidth) . '┐';
+        $line3 = '└' . str_repeat('─', $innerWidth) . '┘';
+
+        $output->writeln('');
+        $output->writeln('<fg=blue;options=bold>' . $line1 . '</>');
+        $output->writeln('<fg=blue;options=bold>' . $line2 . '</>');
+        $output->writeln('<fg=blue;options=bold>' . $line3 . '</>');
+        $output->writeln('');
+    }
+
+    // ═══════════════════════════════════════════════════════════════
+    // Signal handling (Ctrl+C)
+    // ═══════════════════════════════════════════════════════════════
+
+    /**
+     * Register Ctrl+C (SIGINT) handler to show a friendly message on interrupt.
+     * Gracefully skipped when the required extensions are unavailable.
+     */
+    private static function registerInterruptHandler(): void
+    {
+        // Unix/Linux/Mac: pcntl extension with async signals for immediate delivery
+        /*if (function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) {
+            pcntl_async_signals(true);
+            pcntl_signal(\SIGINT, [self::class, 'handleInterrupt']);
+            return;
+        }*/
+
+        // Windows: sapi ctrl handler (PHP >= 7.4)
+        if (function_exists('sapi_windows_set_ctrl_handler')) {
+            sapi_windows_set_ctrl_handler(static function (int $event) {
+                if ($event === \PHP_WINDOWS_EVENT_CTRL_C) {
+                    self::handleInterrupt();
+                }
+            });
+        }
+    }
+
+    /**
+     * Handle Ctrl+C: restore terminal, show tip, then exit.
+     */
+    private static function handleInterrupt(): void
+    {
+        // Restore terminal if in raw mode
+        if (self::$sttyMode !== null && function_exists('shell_exec')) {
+            @shell_exec('stty ' . self::$sttyMode);
+            self::$sttyMode = null;
+        }
+
+        $output = new ConsoleOutput();
+        $output->writeln('');
+        $output->writeln('<comment>' . (self::INTERRUPTED_MESSAGES[self::$interruptLocale] ?? self::INTERRUPTED_MESSAGES['en']) . '</comment>');
+        exit(1);
+    }
+
+    // ═══════════════════════════════════════════════════════════════
+    // Interactive Menu System
+    // ═══════════════════════════════════════════════════════════════
+
+    /**
+     * Check if terminal supports interactive features (arrow keys, ANSI colors).
+     */
+    private static function supportsInteractive(): bool
+    {
+        return function_exists('shell_exec') && Terminal::hasSttyAvailable();
+    }
+
+    /**
+     * Display a selection menu with arrow key navigation (if supported) or text input fallback.
+     *
+     * @param IOInterface $io   Composer IO
+     * @param string      $title Menu title
+     * @param array       $items Indexed array of ['tag' => string, 'label' => string]
+     * @param int         $default Default selected index (0-based)
+     * @return int Selected index
+     */
+    private static function selectMenu(IOInterface $io, string $title, array $items, int $default = 0): int
+    {
+        // Append localized "default" hint to avoid ambiguity
+        // (Template should contain a single %s placeholder for the default tag.)
+        $defaultHintTemplate = null;
+        if (isset(self::MESSAGES[self::$interruptLocale]['default_choice'])) {
+            $defaultHintTemplate = self::MESSAGES[self::$interruptLocale]['default_choice'];
+        }
+
+        $defaultTag = $items[$default]['tag'] ?? '';
+        if ($defaultHintTemplate && $defaultTag !== '') {
+            $title .= sprintf($defaultHintTemplate, $defaultTag);
+        } elseif ($defaultTag !== '') {
+            // Fallback for early menus (e.g. locale selection) before locale is chosen.
+            $title .= sprintf(' (default %s)', $defaultTag);
+        }
+
+        if (self::supportsInteractive()) {
+            return self::arrowKeySelect($title, $items, $default);
+        }
+
+        return self::fallbackSelect($io, $title, $items, $default);
+    }
+
+    /**
+     * Display a yes/no confirmation as a selection menu.
+     *
+     * @param IOInterface $io    Composer IO
+     * @param string      $title Menu title
+     * @param bool        $default Default value (true = yes)
+     * @return bool User's choice
+     */
+    private static function confirmMenu(IOInterface $io, string $title, bool $default = true): bool
+    {
+        $locale = self::$interruptLocale;
+        $yes = self::MESSAGES[$locale]['yes'] ?? self::MESSAGES['en']['yes'] ?? 'yes';
+        $no = self::MESSAGES[$locale]['no'] ?? self::MESSAGES['en']['no'] ?? 'no';
+        $items = $default
+            ? [['tag' => 'Y', 'label' => $yes], ['tag' => 'n', 'label' => $no]]
+            : [['tag' => 'y', 'label' => $yes], ['tag' => 'N', 'label' => $no]];
+        $defaultIndex = $default ? 0 : 1;
+
+        return self::selectMenu($io, $title, $items, $defaultIndex) === 0;
+    }
+
+    /**
+     * Interactive select with arrow key navigation, manual input and ANSI reverse-video highlighting.
+     * Input area and option list highlighting are bidirectionally linked.
+     * Requires stty (Unix-like terminals).
+     */
+    private static function arrowKeySelect(string $title, array $items, int $default): int
+    {
+        $output = new ConsoleOutput();
+        $count = count($items);
+        $selected = $default;
+
+        $maxTagWidth = max(array_map(fn(array $item) => mb_strlen($item['tag']), $items));
+        $defaultTag = $items[$default]['tag'];
+        $input = $defaultTag;
+
+        // Print title and initial options
+        $output->writeln('');
+        $output->writeln('<fg=blue;options=bold>' . $title . '</>');
+        self::drawMenuItems($output, $items, $selected, $maxTagWidth);
+        $output->write('> ' . $input);
+
+        // Enter raw mode
+        self::$sttyMode = shell_exec('stty -g');
+        shell_exec('stty -icanon -echo');
+
+        try {
+            while (!feof(STDIN)) {
+                $c = fread(STDIN, 1);
+
+                if (false === $c || '' === $c) {
+                    break;
+                }
+
+                // ── Backspace ──
+                if ("\177" === $c || "\010" === $c) {
+                    if ('' !== $input) {
+                        $input = mb_substr($input, 0, -1);
+                    }
+                    $selected = self::findItemByTag($items, $input);
+                    $output->write("\033[{$count}A");
+                    self::drawMenuItems($output, $items, $selected, $maxTagWidth);
+                    $output->write("\033[2K\r> " . $input);
+                    continue;
+                }
+
+                // ── Escape sequences (arrow keys) ──
+                if ("\033" === $c) {
+                    $seq = fread(STDIN, 2);
+                    if (isset($seq[1])) {
+                        $changed = false;
+                        if ('A' === $seq[1]) { // Up
+                            $selected = ($selected <= 0 ? $count : $selected) - 1;
+                            $changed = true;
+                        } elseif ('B' === $seq[1]) { // Down
+                            $selected = ($selected + 1) % $count;
+                            $changed = true;
+                        }
+                        if ($changed) {
+                            // Sync input with selected item's tag
+                            $input = $items[$selected]['tag'];
+                            $output->write("\033[{$count}A");
+                            self::drawMenuItems($output, $items, $selected, $maxTagWidth);
+                            $output->write("\033[2K\r> " . $input);
+                        }
+                    }
+                    continue;
+                }
+
+                // ── Enter: confirm selection ──
+                if ("\n" === $c || "\r" === $c) {
+                    if ($selected < 0) {
+                        $selected = $default;
+                    }
+                    $output->write("\033[2K\r> <info>" . $items[$selected]['tag'] . ' ' . $items[$selected]['label'] . '</info>');
+                    $output->writeln('');
+                    break;
+                }
+
+                // ── Ignore other control characters ──
+                if (ord($c) < 32) {
+                    continue;
+                }
+
+                // ── Printable character (with UTF-8 multi-byte support) ──
+                if ("\x80" <= $c) {
+                    $extra = ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3];
+                    $c .= fread(STDIN, $extra[$c & "\xF0"] ?? 0);
+                }
+                $input .= $c;
+                $selected = self::findItemByTag($items, $input);
+                $output->write("\033[{$count}A");
+                self::drawMenuItems($output, $items, $selected, $maxTagWidth);
+                $output->write("\033[2K\r> " . $input);
+            }
+        } finally {
+            if (self::$sttyMode !== null) {
+                shell_exec('stty ' . self::$sttyMode);
+                self::$sttyMode = null;
+            }
+        }
+
+        return $selected < 0 ? $default : $selected;
+    }
+
+    /**
+     * Fallback select for terminals without stty support. Uses plain text input.
+     */
+    private static function fallbackSelect(IOInterface $io, string $title, array $items, int $default): int
+    {
+        $maxTagWidth = max(array_map(fn(array $item) => mb_strlen($item['tag']), $items));
+        $defaultTag = $items[$default]['tag'];
+
+        $io->write('');
+        $io->write('<fg=blue;options=bold>' . $title . '</>');
+        foreach ($items as $item) {
+            $tag = str_pad($item['tag'], $maxTagWidth);
+            $io->write("  [$tag] " . $item['label']);
+        }
+
+        while (true) {
+            $io->write('> ', false);
+            $line = fgets(STDIN);
+            if ($line === false) {
+                return $default;
+            }
+            $answer = trim($line);
+
+            if ($answer === '') {
+                $io->write('> <info>' . $items[$default]['tag'] . ' ' . $items[$default]['label'] . '</info>');
+                return $default;
+            }
+
+            // Match by tag (case-insensitive)
+            foreach ($items as $i => $item) {
+                if (strcasecmp($item['tag'], $answer) === 0) {
+                    $io->write('> <info>' . $items[$i]['tag'] . ' ' . $items[$i]['label'] . '</info>');
+                    return $i;
+                }
+            }
+        }
+    }
+
+    /**
+     * Render menu items with optional ANSI reverse-video highlighting for the selected item.
+     * When $selected is -1, no item is highlighted.
+     */
+    private static function drawMenuItems(ConsoleOutput $output, array $items, int $selected, int $maxTagWidth): void
+    {
+        foreach ($items as $i => $item) {
+            $tag = str_pad($item['tag'], $maxTagWidth);
+            $line = "  [$tag] " . $item['label'];
+            if ($i === $selected) {
+                $output->writeln("\033[2K\r\033[7m" . $line . "\033[0m");
+            } else {
+                $output->writeln("\033[2K\r" . $line);
+            }
+        }
+    }
+
+    /**
+     * Find item index by tag (case-insensitive exact match).
+     * Returns -1 if no match found or input is empty.
+     */
+    private static function findItemByTag(array $items, string $input): int
+    {
+        if ($input === '') {
+            return -1;
+        }
+        foreach ($items as $i => $item) {
+            if (strcasecmp($item['tag'], $input) === 0) {
+                return $i;
+            }
+        }
+        return -1;
+    }
+
+    // ═══════════════════════════════════════════════════════════════
+    // Locale selection
+    // ═══════════════════════════════════════════════════════════════
+
+    private static function askLocale(IOInterface $io): string
+    {
+        $locales = array_keys(self::LOCALE_LABELS);
+        $items = [];
+        foreach ($locales as $i => $code) {
+            $items[] = ['tag' => (string) $i, 'label' => self::LOCALE_LABELS[$code] . " ($code)"];
+        }
+
+        $selected = self::selectMenu(
+            $io,
+            '语言 / Language / 言語 / 언어',
+            $items,
+            0
+        );
+
+        return $locales[$selected];
+    }
+
+    // ═══════════════════════════════════════════════════════════════
+    // Timezone selection
+    // ═══════════════════════════════════════════════════════════════
+
+    private static function askTimezone(IOInterface $io, callable $msg, string $default): string
+    {
+        if (self::supportsInteractive()) {
+            return self::askTimezoneAutocomplete($msg, $default);
+        }
+
+        return self::askTimezoneSelect($io, $msg, $default);
+    }
+
+    /**
+     * Option A: when stty is available, custom character-by-character autocomplete
+     * (case-insensitive, substring match). Interaction: type to filter, hint on right;
+     * ↑↓ change candidate, Tab accept, Enter confirm; empty input = use default.
+     */
+    private static function askTimezoneAutocomplete(callable $msg, string $default): string
+    {
+        $allTimezones = \DateTimeZone::listIdentifiers();
+        $output = new ConsoleOutput();
+        $cursor = new Cursor($output);
+
+        $output->writeln('');
+        $output->writeln('<fg=blue;options=bold>' . $msg('timezone_title', $default) . '</>');
+        $output->writeln($msg('timezone_help'));
+        $output->write('> ');
+
+        self::$sttyMode = shell_exec('stty -g');
+        shell_exec('stty -icanon -echo');
+
+        // Auto-fill default timezone in the input area; user can edit it directly.
+        $input = $default;
+        $output->write($input);
+
+        $ofs = 0;
+        $matches = self::filterTimezones($allTimezones, $input);
+        if (!empty($matches)) {
+            $hint = $matches[$ofs % count($matches)];
+            // Avoid duplicating hint when input already fully matches the only candidate.
+            if (!(count($matches) === 1 && $hint === $input)) {
+                $cursor->clearLineAfter();
+                $cursor->savePosition();
+                $output->write('  <fg=blue;options=bold>' . $hint . '</>');
+                if (count($matches) > 1) {
+                    $output->write('  <info>(' . count($matches) . ' matches, ↑↓)</info>');
+                }
+                $cursor->restorePosition();
+            }
+        }
+
+        try {
+            while (!feof(STDIN)) {
+                $c = fread(STDIN, 1);
+
+                if (false === $c || '' === $c) {
+                    break;
+                }
+
+                // ── Backspace ──
+                if ("\177" === $c || "\010" === $c) {
+                    if ('' !== $input) {
+                        $lastChar = mb_substr($input, -1);
+                        $input = mb_substr($input, 0, -1);
+                        $cursor->moveLeft(max(1, mb_strwidth($lastChar)));
+                    }
+                    $ofs = 0;
+
+                    // ── Escape sequences (arrows) ──
+                } elseif ("\033" === $c) {
+                    $seq = fread(STDIN, 2);
+                    if (isset($seq[1]) && !empty($matches)) {
+                        if ('A' === $seq[1]) {
+                            $ofs = ($ofs - 1 + count($matches)) % count($matches);
+                        } elseif ('B' === $seq[1]) {
+                            $ofs = ($ofs + 1) % count($matches);
+                        }
+                    }
+
+                    // ── Tab: accept current match ──
+                } elseif ("\t" === $c) {
+                    if (isset($matches[$ofs])) {
+                        self::replaceInput($output, $cursor, $input, $matches[$ofs]);
+                        $input   = $matches[$ofs];
+                        $matches = [];
+                    }
+                    $cursor->clearLineAfter();
+                    continue;
+
+                    // ── Enter: confirm ──
+                } elseif ("\n" === $c || "\r" === $c) {
+                    if (isset($matches[$ofs])) {
+                        self::replaceInput($output, $cursor, $input, $matches[$ofs]);
+                        $input = $matches[$ofs];
+                    }
+                    if ($input === '') {
+                        $input = $default;
+                    }
+                    // Re-render user input with <comment> style
+                    $cursor->moveToColumn(1);
+                    $cursor->clearLine();
+                    $output->write('> <info>' . $input . '</info>');
+                    $output->writeln('');
+                    break;
+
+                    // ── Other control chars: ignore ──
+                } elseif (ord($c) < 32) {
+                    continue;
+
+                    // ── Printable character ──
+                } else {
+                    if ("\x80" <= $c) {
+                        $extra = ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3];
+                        $c .= fread(STDIN, $extra[$c & "\xF0"] ?? 0);
+                    }
+                    $output->write($c);
+                    $input .= $c;
+                    $ofs = 0;
+                }
+
+                // Update match list
+                $matches = self::filterTimezones($allTimezones, $input);
+
+                // Show autocomplete hint
+                $cursor->clearLineAfter();
+                if (!empty($matches)) {
+                    $hint = $matches[$ofs % count($matches)];
+                    $cursor->savePosition();
+                    $output->write('  <fg=blue;options=bold>' . $hint . '</>');
+                    if (count($matches) > 1) {
+                        $output->write('  <info>(' . count($matches) . ' matches, ↑↓)</info>');
+                    }
+                    $cursor->restorePosition();
+                }
+            }
+        } finally {
+            if (self::$sttyMode !== null) {
+                shell_exec('stty ' . self::$sttyMode);
+                self::$sttyMode = null;
+            }
+        }
+
+        $result = '' === $input ? $default : $input;
+
+        if (!in_array($result, $allTimezones, true)) {
+            $output->writeln('<comment>' . $msg('timezone_invalid', $default) . '</comment>');
+            return $default;
+        }
+
+        return $result;
+    }
+
+    /**
+     * Clear current input and replace with new text.
+     */
+    private static function replaceInput(ConsoleOutput $output, Cursor $cursor, string $oldInput, string $newInput): void
+    {
+        if ('' !== $oldInput) {
+            $cursor->moveLeft(mb_strwidth($oldInput));
+        }
+        $cursor->clearLineAfter();
+        $output->write($newInput);
+    }
+
+    /**
+     * Case-insensitive substring match for timezones.
+     */
+    private static function filterTimezones(array $timezones, string $input): array
+    {
+        if ('' === $input) {
+            return [];
+        }
+        $lower = mb_strtolower($input);
+        return array_values(array_filter(
+            $timezones,
+            fn(string $tz) => str_contains(mb_strtolower($tz), $lower)
+        ));
+    }
+
+    /**
+     * Find an exact timezone match (case-insensitive).
+     * Returns the correctly-cased system timezone name, or null if not found.
+     */
+    private static function findExactTimezone(array $allTimezones, string $input): ?string
+    {
+        $lower = mb_strtolower($input);
+        foreach ($allTimezones as $tz) {
+            if (mb_strtolower($tz) === $lower) {
+                return $tz;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Search timezones by keyword (substring) and similarity.
+     * Returns combined results: substring matches first, then similarity matches (>=50%).
+     *
+     * @param string[] $allTimezones All valid timezone identifiers
+     * @param string   $keyword      User input to search for
+     * @param int      $limit        Maximum number of results
+     * @return string[] Matched timezone identifiers
+     */
+    private static function searchTimezones(array $allTimezones, string $keyword, int $limit = 15): array
+    {
+        // 1. Substring matches (higher priority)
+        $substringMatches = self::filterTimezones($allTimezones, $keyword);
+        if (count($substringMatches) >= $limit) {
+            return array_slice($substringMatches, 0, $limit);
+        }
+
+        // 2. Similarity matches for remaining slots (normalized: strip _ and /)
+        $substringSet = array_flip($substringMatches);
+        $normalizedKeyword = str_replace(['_', '/'], ' ', mb_strtolower($keyword));
+        $similarityMatches = [];
+
+        foreach ($allTimezones as $tz) {
+            if (isset($substringSet[$tz])) {
+                continue;
+            }
+            $parts = explode('/', $tz);
+            $city = str_replace('_', ' ', mb_strtolower(end($parts)));
+            $normalizedTz = str_replace(['_', '/'], ' ', mb_strtolower($tz));
+
+            similar_text($normalizedKeyword, $city, $cityPercent);
+            similar_text($normalizedKeyword, $normalizedTz, $fullPercent);
+
+            $bestPercent = max($cityPercent, $fullPercent);
+            if ($bestPercent >= 50.0) {
+                $similarityMatches[] = ['tz' => $tz, 'score' => $bestPercent];
+            }
+        }
+
+        usort($similarityMatches, fn(array $a, array $b) => $b['score'] <=> $a['score']);
+
+        $results = $substringMatches;
+        foreach ($similarityMatches as $item) {
+            $results[] = $item['tz'];
+            if (count($results) >= $limit) {
+                break;
+            }
+        }
+
+        return $results;
+    }
+
+    /**
+     * Option B: when stty is not available (e.g. Windows), keyword search with numbered list.
+     * Flow: enter timezone/keyword → exact match uses it directly; otherwise show
+     * numbered results (substring + similarity) → pick by number or refine keyword.
+     */
+    private static function askTimezoneSelect(IOInterface $io, callable $msg, string $default): string
+    {
+        $allTimezones = \DateTimeZone::listIdentifiers();
+
+        $io->write('');
+        $io->write('<fg=blue;options=bold>' . $msg('timezone_title', $default) . '</>');
+        $io->write($msg('timezone_input_prompt'));
+
+        /** @var string[]|null Currently displayed search result list */
+        $currentList = null;
+
+        while (true) {
+            $io->write('> ', false);
+            $line = fgets(STDIN);
+            if ($line === false) {
+                return $default;
+            }
+            $answer = trim($line);
+
+            // Empty input → use default
+            if ($answer === '') {
+                $io->write('> <info>' . $default . '</info>');
+                return $default;
+            }
+
+            // If a numbered list is displayed and input is a pure number
+            if ($currentList !== null && ctype_digit($answer)) {
+                $idx = (int) $answer;
+                if (isset($currentList[$idx])) {
+                    $io->write('> <info>' . $currentList[$idx] . '</info>');
+                    return $currentList[$idx];
+                }
+                $io->write('<comment>' . $msg('timezone_invalid_index') . '</comment>');
+                continue;
+            }
+
+            // Exact case-insensitive match → return the correctly-cased system value
+            $exact = self::findExactTimezone($allTimezones, $answer);
+            if ($exact !== null) {
+                $io->write('> <info>' . $exact . '</info>');
+                return $exact;
+            }
+
+            // Keyword + similarity search
+            $results = self::searchTimezones($allTimezones, $answer);
+
+            if (empty($results)) {
+                $io->write('<comment>' . $msg('timezone_no_match') . '</comment>');
+                $currentList = null;
+                continue;
+            }
+
+            // Single result → use it directly
+            if (count($results) === 1) {
+                $io->write('> <info>' . $results[0] . '</info>');
+                return $results[0];
+            }
+
+            // Display numbered list
+            $currentList = $results;
+            $padWidth = strlen((string) (count($results) - 1));
+            foreach ($results as $i => $tz) {
+                $io->write('  [' . str_pad((string) $i, $padWidth) . '] ' . $tz);
+            }
+            $io->write($msg('timezone_pick_prompt'));
+        }
+    }
+
+    // ═══════════════════════════════════════════════════════════════
+    // Optional component selection
+    // ═══════════════════════════════════════════════════════════════
+
+    private static function askComponents(IOInterface $io, callable $msg): array
+    {
+        $packages = [];
+        $addPackage = static function (string $package) use (&$packages, $io, $msg): void {
+            if (in_array($package, $packages, true)) {
+                return;
+            }
+            $packages[] = $package;
+            $io->write($msg('adding_package', '<info>' . $package . '</info>'));
+        };
+
+        // Console (default: yes)
+        if (self::confirmMenu($io, $msg('console_question'), true)) {
+            $addPackage(self::PACKAGE_CONSOLE);
+        }
+
+        // Database
+        $dbItems = [
+            ['tag' => '0', 'label' => $msg('db_none')],
+            ['tag' => '1', 'label' => 'webman/database'],
+            ['tag' => '2', 'label' => 'webman/think-orm'],
+            ['tag' => '3', 'label' => 'webman/database && webman/think-orm'],
+        ];
+        $dbChoice = self::selectMenu($io, $msg('db_question'), $dbItems, 0);
+        if ($dbChoice === 1) {
+            $addPackage(self::PACKAGE_DATABASE);
+        } elseif ($dbChoice === 2) {
+            $addPackage(self::PACKAGE_THINK_ORM);
+        } elseif ($dbChoice === 3) {
+            $addPackage(self::PACKAGE_DATABASE);
+            $addPackage(self::PACKAGE_THINK_ORM);
+        }
+
+        // If webman/database is selected, add required dependencies automatically
+        if (in_array(self::PACKAGE_DATABASE, $packages, true)) {
+            $addPackage(self::PACKAGE_ILLUMINATE_PAGINATION);
+            $addPackage(self::PACKAGE_ILLUMINATE_EVENTS);
+            $addPackage(self::PACKAGE_SYMFONY_VAR_DUMPER);
+        }
+
+        // Redis (default: no)
+        if (self::confirmMenu($io, $msg('redis_question'), false)) {
+            $addPackage(self::PACKAGE_REDIS);
+            $addPackage(self::PACKAGE_ILLUMINATE_EVENTS);
+        }
+
+        // Validation (default: no)
+        if (self::confirmMenu($io, $msg('validation_question'), false)) {
+            $addPackage(self::PACKAGE_VALIDATION);
+        }
+
+        // Template engine
+        $tplItems = [
+            ['tag' => '0', 'label' => $msg('template_none')],
+            ['tag' => '1', 'label' => 'webman/blade'],
+            ['tag' => '2', 'label' => 'twig/twig'],
+            ['tag' => '3', 'label' => 'topthink/think-template'],
+        ];
+        $tplChoice = self::selectMenu($io, $msg('template_question'), $tplItems, 0);
+        if ($tplChoice === 1) {
+            $addPackage(self::PACKAGE_BLADE);
+        } elseif ($tplChoice === 2) {
+            $addPackage(self::PACKAGE_TWIG);
+        } elseif ($tplChoice === 3) {
+            $addPackage(self::PACKAGE_THINK_TEMPLATE);
+        }
+
+        return $packages;
+    }
+
+    // ═══════════════════════════════════════════════════════════════
+    // Config file update
+    // ═══════════════════════════════════════════════════════════════
+
+    /**
+     * Update a config value like 'key' => 'old_value' in the given file.
+     */
+    private static function updateConfig(Event $event, string $relativePath, string $key, string $newValue): void
+    {
+        $root = dirname($event->getComposer()->getConfig()->get('vendor-dir'));
+        $file = $root . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $relativePath);
+        if (!is_readable($file)) {
+            return;
+        }
+        $content = file_get_contents($file);
+        if ($content === false) {
+            return;
+        }
+        $pattern = '/' . preg_quote($key, '/') . "\s*=>\s*'[^']*'/";
+        $replacement = $key . " => '" . $newValue . "'";
+        $newContent = preg_replace($pattern, $replacement, $content);
+        if ($newContent !== null && $newContent !== $content) {
+            file_put_contents($file, $newContent);
+        }
+    }
+
+    // ═══════════════════════════════════════════════════════════════
+    // Composer require
+    // ═══════════════════════════════════════════════════════════════
+
+    private static function runComposerRequire(array $packages, IOInterface $io, callable $msg): void
+    {
+        $io->write('<comment>' . $msg('running') . '</comment> composer require ' . implode(' ', $packages));
+        $io->write('');
+
+        $code = self::runComposerCommand('require', $packages);
+
+        if ($code !== 0) {
+            $io->writeError('<error>' . $msg('error_install', implode(' ', $packages)) . '</error>');
+        } else {
+            $io->write('<info>' . $msg('done') . '</info>');
+        }
+    }
+
+    private static function askRemoveComponents(Event $event, array $selectedPackages, IOInterface $io, callable $msg): array
+    {
+        $requires = $event->getComposer()->getPackage()->getRequires();
+        $allOptionalPackages = [
+            self::PACKAGE_CONSOLE,
+            self::PACKAGE_DATABASE,
+            self::PACKAGE_THINK_ORM,
+            self::PACKAGE_REDIS,
+            self::PACKAGE_ILLUMINATE_EVENTS,
+            self::PACKAGE_ILLUMINATE_PAGINATION,
+            self::PACKAGE_SYMFONY_VAR_DUMPER,
+            self::PACKAGE_VALIDATION,
+            self::PACKAGE_BLADE,
+            self::PACKAGE_TWIG,
+            self::PACKAGE_THINK_TEMPLATE,
+        ];
+
+        $secondaryPackages = [
+            self::PACKAGE_ILLUMINATE_EVENTS,
+            self::PACKAGE_ILLUMINATE_PAGINATION,
+            self::PACKAGE_SYMFONY_VAR_DUMPER,
+        ];
+
+        $installedOptionalPackages = [];
+        foreach ($allOptionalPackages as $pkg) {
+            if (isset($requires[$pkg])) {
+                $installedOptionalPackages[] = $pkg;
+            }
+        }
+
+        $allPackagesToRemove = array_diff($installedOptionalPackages, $selectedPackages);
+
+        if (count($allPackagesToRemove) === 0) {
+            return [];
+        }
+
+        $displayPackagesToRemove = array_diff($allPackagesToRemove, $secondaryPackages);
+
+        if (count($displayPackagesToRemove) === 0) {
+            return $allPackagesToRemove;
+        }
+
+        $pkgListStr = "";
+        foreach ($displayPackagesToRemove as $pkg) {
+            $pkgListStr .= "\n  - {$pkg}";
+        }
+        $pkgListStr .= "\n";
+
+        $title = '<comment>' . $msg('remove_package_question', '') . '</comment>' . $pkgListStr;
+        if (self::confirmMenu($io, $title, false)) {
+            return $allPackagesToRemove;
+        }
+
+        return [];
+    }
+
+    private static function runComposerRemove(array $packages, IOInterface $io, callable $msg): void
+    {
+        $io->write('<comment>' . $msg('running') . '</comment> composer remove ' . implode(' ', $packages));
+        $io->write('');
+
+        $code = self::runComposerCommand('remove', $packages);
+
+        if ($code !== 0) {
+            $io->writeError('<error>' . $msg('error_remove', implode(' ', $packages)) . '</error>');
+        } else {
+            $io->write('<info>' . $msg('done_remove') . '</info>');
+        }
+    }
+
+    /**
+     * Run a Composer command (require/remove) in-process via Composer's Application API.
+     * No shell execution functions needed — works even when passthru/exec/shell_exec are disabled.
+     */
+    private static function runComposerCommand(string $command, array $packages): int
+    {
+        try {
+            // Already inside a user-initiated Composer session — suppress duplicate root/superuser warnings
+            $_SERVER['COMPOSER_ALLOW_SUPERUSER'] = '1';
+            if (function_exists('putenv')) {
+                putenv('COMPOSER_ALLOW_SUPERUSER=1');
+            }
+
+            $application = new ComposerApplication();
+            $application->setAutoExit(false);
+
+            return $application->run(
+                new ArrayInput([
+                    'command'  => $command,
+                    'packages' => $packages,
+                    '--no-interaction' => true,
+                    '--update-with-all-dependencies' => true,
+                ]),
+                new ConsoleOutput()
+            );
+        } catch (\Throwable) {
+            return 1;
+        }
+    }
+}

+ 3 - 0
support/bootstrap.php

@@ -0,0 +1,3 @@
+<?php
+
+require_once __DIR__ . '/../vendor/workerman/webman-framework/src/support/bootstrap.php';

+ 2 - 0
vendor/aliyuncs/oss-sdk-php/.coveralls.yml

@@ -0,0 +1,2 @@
+coverage_clover: coverage.xml
+json_path: coverage.json

+ 45 - 0
vendor/aliyuncs/oss-sdk-php/.github/workflows/main.yml

@@ -0,0 +1,45 @@
+name: CI
+on: [push, pull_request]
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  phpunit:
+    name: PHPUnit (PHP ${{ matrix.php-version }} on ${{ matrix.operating-system }})
+    runs-on: ${{ matrix.operating-system }}
+    strategy:
+      fail-fast: false
+      matrix:
+        operating-system: [ubuntu-latest, windows-latest]
+        php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']
+    steps:
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
+        with:
+          php-version: ${{ matrix.php-version }}
+          extensions: curl, mbstring, openssl, xml
+          coverage: none
+
+      - name: Checkout
+        uses: actions/checkout@v4
+
+      - name: Install dependencies
+        run: composer install --ansi --prefer-dist --no-interaction --no-progress
+
+      - name: PHPUnit Migrate Configuration
+        if: ${{ matrix.php-version >= '8.0' }}
+        run: vendor/bin/phpunit --migrate-configuration
+
+      - name: Run Unit Tests (PHP 5.6 - 8.0)
+        if: ${{ matrix.php-version < '8.1' }}
+        run: vendor/bin/phpunit --testsuite UnitTest
+        env:
+          PHP_ERROR_REPORTING: E_ALL
+
+      - name: Run Unit Tests (PHP 8.1+)
+        if: ${{ matrix.php-version >= '8.1' }}
+        run: vendor/bin/phpunit --testsuite UnitTest --fail-on-deprecation --display-deprecations
+        env:
+          PHP_ERROR_REPORTING: E_ALL

+ 35 - 0
vendor/aliyuncs/oss-sdk-php/.github/workflows/release.yml

@@ -0,0 +1,35 @@
+name: Release
+
+on:
+  release:
+    types: [published]
+
+jobs:
+  build-phar:
+    name: Build PHAR
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
+        with:
+          php-version: '7.4'
+          extensions: phar, curl, mbstring, openssl, xml
+          tools: phar-composer
+
+      - name: Install dependencies
+        run: composer install --no-dev --prefer-dist --no-interaction --no-progress
+
+      - name: Build PHAR
+        run: |
+          version=$(grep 'const OSS_VERSION' src/OSS/OssClient.php | grep -oE '[0-9.]+')
+          phar-composer build . aliyun-oss-php-sdk-${version}.phar
+
+      - name: Upload to Release
+        env:
+          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        run: |
+          version=$(grep 'const OSS_VERSION' src/OSS/OssClient.php | grep -oE '[0-9.]+')
+          gh release upload ${{ github.event.release.tag_name }} aliyun-oss-php-sdk-${version}.phar

+ 8 - 0
vendor/aliyuncs/oss-sdk-php/.gitignore

@@ -0,0 +1,8 @@
+vendor
+composer.lock
+doc
+output
+.idea
+.buildpath
+.project
+.settings

+ 21 - 0
vendor/aliyuncs/oss-sdk-php/.travis.yml

@@ -0,0 +1,21 @@
+language: php
+php:
+  - 7.1
+  - 7.0
+  - 5.6
+  - 5.5
+  - 5.4
+install:
+  - composer self-update
+  - composer install --no-interaction
+script:
+  - php vendor/bin/phpunit
+after_success:
+  - php vendor/bin/coveralls -v
+env:
+  global:
+    - secure: SzmQ854lQmhV6ZkAG7lQNTY3CkazrXnDSb6VMwPU/sdaLGxPO159AW3fJS5d0sO/XN1P8x5WNkoA4i9soDlLBRibEEISNUM/2EMnpszsRymZ9o97PrS2IgORXTUL/OF+rpATzyNVB2p+2l9hBLiGf17exMSA5iOeY7W6E+VKPGi8TFykgbGUnLKU0h1hV3rzmtfGjOXcSpvYU/hxeZD/J/+6m5Gic9b/pNS+AbfTj7Y7Ru9tNsnyUP29V/vtEYtpQir3ZxQiSiUv9idybgGnJBOMYydJofb/mpFYHhYLSWqtMKGNLpeawmqs4z8S1Tvx5U5uzW5+h/mpzhvBaFlWGpm8t89BQxun5LVX5NiYCrV7TqaLitGp1cSpMjMDnrnSTNzk1exVz+rWZZcWS7yB9ULYA681GA8StXWk167qB7Y30iK1dFK3+2mDN2cEY+qLs8+bupDowQ4eOM+eqfhxX8F8+ouKcKomETsjiIwL+CUsIe6wjvnYFWb1YlRhbsI75bblHApflohnt6gVSJ78ZPqID+u2oUMjmIWXLTnRR2Y2tgEW8uqHeIoQ8BBntLdQDmv0BO4FpnGQIwrUUwQYeNzEM0DOr3hWZhyDR6Xvl+9H0l52xjANaSqpuTZfC3zmeFTG7kIjydvxNePRrony6XAawL9BvI7aKWuVF6YVjPM=
+    - secure: nEhsU8aUQqsAJeuger+boh51oTpeo4YNG7vUWbKxdwVDIrcLb+l7r7RvTlxU7mt8IZTWwicgri18mh+Wi04BwX4ulBA1SCs8jPbL51KEo5izoDGGtLSd2fuPHdslYSrwagrvq90EPnDT/7fHWn/TAoT+rueZzjNyCu5IGSgL3GnXaUThsJ82NMePL2YRdP4Q1qmtZPRFBOkOQ6F0heuV8fw8sLyTO3txaCQum9YneGxrWxOl/E8zB0qtlnPwLE8ogaHZMQh2/jThmTbI5UqwRTxV4f0qoD5eJYH+j0fslsSAjsg/HPnSuVcnccK3zSU+s2sV4dPCcISzECJvZEObwipfxOGhdqt5gMcxHhn8qVsbT97iIh106pG/BJCDgQd2EeVW8WfCi6cCuCKIMipvVkMypkmjQHWU1XaqPzILl7g5diW9Ctp2C4Akq5dYdrdu8IrnVK1ShtkQVaWU+S/Bht8VU5gYP7olPW/GdTz7sceU1NOIC4NPXqmWKbfavR98U5dkHMLMvzABYL1Q87h+KhPD1c14NUyw3YENUW7REiF/X5lERRm5H0kJ/1JqAa+AgeHQEGmPVuZV2s/na4b0S1479QRVmSM/6ZzXQpU+Y8jCRfETpUFA4S331369kirHgCqDlxyIntuEKrzivD02/O+5C3eJ0WHRz6QsN2/R4qg=
+    - secure: ZTvzNXEZP4efl+a/3VGMmdabfUQp83v5/lecMns039Ro7UuZYPdtbPtpPnpjaTI6Htd22A4Rva5BU/3JCQJAyQvpbKNn5sGou2SmfQu3o0SyhggSB7gWjYAf707aW1j4bHYfP8IjDS5NjuVk3AqXeNSUuLRUXRmwSOB0lSYiRhiTJY+pUdBl382Hx4NbhIU/gmOzRoJCs7coTip8IURXYEHPi5dnDWluajxI+TgNXFccSgEleeQDJajYgXmpLb2EhSj8piipOnVgaCEE5bh5fbp32024Qq38SGHKcbfnwj2IInpZpZESJknRKoqAlFjdOJhork82dBcvAr5JxCBZKx5IuwXcTjxkQ6tRtBeqhPLPFuX3MQ8WrtU+wniPM0RCH/VoFkUKO7JGQDwmoi2AKago4PsuDs4P6Y6CeuOVpcso731GwwMNhIJcyrJJivXprQNEGsEw+9wLjU1qNYs6IIA3S/gPzFrNbdX5Wf8vxt0vLpgYvBNtPnLMejMtknuyfVzf5iKuVVoGPDTEz+ajs06+jfoPfm/4sLTaLghuVH7Adm74OpF769JQNnQYKwJuu4bNlcbLJChulCEMBOx7myqo/9O6RCTuqzHaGmVWNot4RGqRFHgJGl/JJf0WpAVitbhbRH3kGoyKb6jFM74CJbPsE7OORlJLDC3cdD3C8Pk=
+    - secure: Qr5NR4CVzBKCQgRgMH0x772TPJ1+brx3UCvtRNu8fi4j3p8bz+HDMjBaBDSFmEB09nunLI55/8mj88/5GXmnpFs8+CPTkcW+QZOcxg3cxpI4SNmxoB12/ZawlFHAqSUaRRE7RUWVkY3KL8tIGjEZcFyUBQ1DVNX3OMpiKs3NLtHa7oUIknyBxdSokm4kpLhSXYe7WmO0vhuZbMZE0S1EISToiBS6AdhGUEbTLJ/vNsIDY07fu6+Vh3HxVbyUFPqUZGlkZpQ+2xMJ3kiqPBMrXtRF/IhhPjORDil6Ns9SQ8/AAlaCddvYvRaT4Pjv2/aX+t3l28qI1qmryPtWXpce5UXecWGYqdRpSJc6Y/pEt4m4FeeGoEFWnSPGIs7FRmeiis8q2rojGZ18i4vI/k4iHmqEBnTlMp3SWnRb9L1adJ8ZAWln8aC88gkQXm67w7+1CxLycerbYj9H1ugqHENuHcxv4uHUcZgEENX3EWatu8i9+K2IUuU/2zcmpu7qtsziYcoyW8DOOmYpJfXGMLtmF9+pqp/Tp6i0tltFSEfmY3N8o7xvv3enLvFHsjL+3ElFdd1blUPSrvZJHgA9M3lJ+QF1RJZCpJqgPlQ0XOZK1Bf4P46zpEj01wKaK4JQrkLPRXhbBOuIJn5O6WlFJyPX4+SaBfwTzb4AvM4aUg2TgTg=
+    - secure: Inw5ftA8fxvhMHRZwoZzATxn4WICJsCq7ZX4y2gI+b/8u0JQIsbLgY9WTYV+XdSxOoNwuVa1oUxEWI0aDORtXKC3XaIXXKrwndag0zxS77JEYwWvQsjM7BhEbF7MF7MYk8rRXpn6mbfGAT/NfqEOx91RCY8UKeMzD0oPkpkBnJ9Ekuod6JBBq+7j3v4mYUItA8pxvw7b4Pdd4z2xzjgOwNhJYMOCpts50DWZI+WXj0HvTYaMXe5mJJtORK5lsr0a9cbsBqAzE6l+3zGI8XkgHn130ux5XH3DE7hZBeti3ZNaO3d2Vv+496/1EObG0rSFk+z3dmNKqjMz4nh3bYIkdLMegwmgCWs2mvQhkwYhzmnPRHVSERrgZjSWnuKn2PKnBar6tui9KaLNgpo2j3jWpwMLJ3bGAfE5JtMppxAxNqj/q+YB2UZo7Mn7EDjkTDjgxCuazTJwWqH7xxCOykWPABBI17P3JaOXQJEK39LavpfSMm3kdmU0ocpUs7FniLuFm6xL71VxY1wHG10yskczEcFHZ3iyIyGM+xum4vbt5y6Yg+zfdExYQsbrxHDDZ3HbHY3tEU0WhM55vrC42NIXRWqXqJ8OAxpl4nivfx96eoBAThiUU9xXtZmh7WRFVYsstoGtxZwfk5+bi+oeVO9kih4xabwbgHgL9BTc1TR1C4U=

+ 163 - 0
vendor/aliyuncs/oss-sdk-php/CHANGELOG.md

@@ -0,0 +1,163 @@
+# ChangeLog - Aliyun OSS SDK for PHP
+
+## v2.7.3 / 2026-06-26
+* Compatible with PHP8.5
+
+
+## v2.7.2 / 2024-10-28
+* Added: presign supports response-* parameters
+* Added: forcePathStyle option.
+
+## v2.7.1 / 2024-02-28
+* Fixed: fix deprecated
+
+## v2.7.0 / 2024-02-02
+* Added: support signature version 4.
+* Added: support checkObjectEndcoding option.
+* Added: support strictObjectName option.
+* Added: support filePathCompatible option.
+* Added: support path style.
+* Added: support environment variables credentials provider.
+* Update: add filed for some api.
+* Fixed: fix some bugs.
+
+## v2.6.0 / 2022-08-03
+* Added: support credentials provider.
+* Fixed: compatible with swoole curl handler.
+* Added: support more bucket stat info.
+
+## v2.5.0 / 2022-05-13
+* Added: support bucket transfer acceleration.
+* Added: support bucket cname token.
+* Added: support listobjectsV2.
+
+## v2.4.3 / 2021-08-25
+* Fixed: integer overflow in PHP5.x.
+
+## v2.4.2 / 2021-06-04
+* Compatible with PHP8.
+* Fixed: compatible with PHP5.4.
+* Fixed: the signature is incorrect in some scenarios
+* Update: change $requestUrl from a member variable to a local variable.
+
+## v2.4.1 / 2020-09-29
+* Fixed: the getBucketPolicy bug.
+
+
+## v2.4.0 / 2020-08-31
+
+* Added: disable Expect: 100-continue
+* Added: support getBucketInfo
+* Added: support getBucketStat
+* Added: support bucket policy
+* Added: support bucket encryption
+* Added: support bucket tagging
+* Added: support bucket  worm
+* Added: support versioning
+* Added: support request payment
+* Added: support object tagging
+* Added: support code archive
+* Added: support process object 
+* Added: support traffic limit paramter 
+* Added: support upload object from file handle
+* Added: support getSimplifiedObjectMeta
+* Fixed: the object name can not be '0' stirng.
+* Update: endpoint validity check
+* Update: add new pre-signed url api
+
+
+## v2.3.1 / 2019-01-15
+
+* translate chinese comments into english
+* Added: endpoint validity check
+
+## v2.3.0 / 2018-01-05
+
+* Fixed: putObject support creating empty files
+* Fixed: createBucket support IA/Archive
+* Added: support restoreObject
+* Added: support the Symlink feature
+* Added: support getBucketLocation
+* Added: support getBucketMeta
+* Added: support proxy server Proxy
+
+## v2.2.4 / 2017-04-25
+
+* Fixed getObject to local file bug
+
+## v2.2.3 / 2017-04-14
+
+* Fixed md5 check
+
+## v2.2.2 / 2017-01-18
+
+* Resolve to run the connection number and memory bug on php7
+
+## v2.2.1 / 2016-12-01
+
+* No HTTP curl is allowed to automatically populate accept-encoding
+
+## v2.2.0 / 2016-11-22
+
+* Fixed PutObject/CompleteMultipartUpload return values(#26)
+
+## v2.1.0 / 2016-11-12
+
+* Added[RTMP](https://help.aliyun.com/document_detail/44297.html)interface
+* Add support[image service](https://help.aliyun.com/document_detail/44686.html)
+
+## v2.0.7 / 2016-06-17
+
+* Support append object
+
+## v2.0.6
+
+* Trim access key id/secret and endpoint
+* Refine tests and setup travis CI
+
+## v2.0.5
+
+* Added Add/Delete/Get BucketCname interface
+
+## v2.0.4
+
+* Added Put/Get Object Acl interface
+
+## v2.0.3
+
+* Fixing the constants in Util is defined in a PHP version that is less than 5.6.
+
+## v2.0.2
+
+* The problem of content-type cannot be specified when restoring multipart uploads
+
+## v2.0.1
+
+* Increase the ListObjects/ListMultipartUploads special characters
+* Provides the interface to get the details of the OssException
+
+
+## 2015.11.25
+
+* **Large version upgrade, no longer compatible with previous interface, new version has made great improvements to ease of use, suggesting that users migrate to a new version.**
+
+## Modify the content
+
+* PHP 5.2 is no longer supported
+
+### Add the cotent
+
+* Introduce namespace
+* Interface naming and modification, using hump naming
+* The interface is modified, and the common parameters are extracted from the Options parameter.
+* The interface returns the result modification, processing the return result, and the user can directly get the data structure easily processed 
+* OssClient's constructor changes
+* The Endpoint address that support CNAME and IP formats
+* Rearrange the sample file organization structure and use function to organize the function points
+* Add an interface that sets the connection timeout and requests timeout
+* Remove the outdated interface associated with the Object Group
+* The message in the OssException is changed to English
+
+### Repair problem
+
+* The object name is not complete

+ 21 - 0
vendor/aliyuncs/oss-sdk-php/LICENSE.md

@@ -0,0 +1,21 @@
+#The MIT License (MIT)
+
+Copyright (c) ali-sdk and other contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 154 - 0
vendor/aliyuncs/oss-sdk-php/README-CN.md

@@ -0,0 +1,154 @@
+# Aliyun OSS SDK for PHP
+
+[![Latest Stable Version](https://poser.pugx.org/aliyuncs/oss-sdk-php/v/stable)](https://packagist.org/packages/aliyuncs/oss-sdk-php)
+[![Build Status](https://travis-ci.org/aliyun/aliyun-oss-php-sdk.svg?branch=master)](https://travis-ci.org/aliyun/aliyun-oss-php-sdk)
+[![Coverage Status](https://coveralls.io/repos/github/aliyun/aliyun-oss-php-sdk/badge.svg?branch=master)](https://coveralls.io/github/aliyun/aliyun-oss-php-sdk?branch=master)
+
+## [README of English](https://github.com/aliyun/aliyun-oss-php-sdk/blob/master/README.md)
+
+## 关于 OSS SDK for PHP V2
+> - OSS SDK for PHP V2([alibabacloud-oss-php-sdk-v2](https://github.com/aliyun/alibabacloud-oss-php-sdk-v2)) 测试版已发布, 是对V1(aliyun-oss-php-sdk)代码库的重大改写。
+> - V2是一个全新的版本,简化了底层操作例如身份验证、自动请求重试及错误处理等;提供了灵活友好的参数配置以及丰富的高级接口,例如分页器、传输管理器等,全面提升了开发效率和体验。
+
+
+## 概述
+
+阿里云对象存储(Object Storage Service,简称OSS),是阿里云对外提供的海量、安全、低成本、高可靠的云存储服务。用户可以通过调用API,在任何应用、任何时间、任何地点上传和下载数据,也可以通过用户Web控制台对数据进行简单的管理。OSS适合存放任意文件类型,适合各种网站、开发企业及开发者使用。
+
+
+## 运行环境
+- PHP 5.3+
+- cURL extension
+
+提示:
+
+- Ubuntu下可以使用apt-get包管理器安装php的cURL扩展 `sudo apt-get install php5-curl`
+
+## 安装方法
+
+1. 如果您通过composer管理您的项目依赖,可以在你的项目根目录运行:
+
+        $ composer require aliyuncs/oss-sdk-php
+
+   或者在你的`composer.json`中声明对Aliyun OSS SDK for PHP的依赖:
+
+        "require": {
+            "aliyuncs/oss-sdk-php": "~2.0"
+        }
+
+   然后通过`composer install`安装依赖。composer安装完成后,在您的PHP代码中引入依赖即可:
+
+        require_once __DIR__ . '/vendor/autoload.php';
+
+2. 您也可以直接下载已经打包好的[phar文件][releases-page],然后在你
+   的代码中引入这个文件即可:
+
+        require_once '/path/to/oss-sdk-php.phar';
+
+3. 下载SDK源码,在您的代码中引入SDK目录下的`autoload.php`文件:
+
+        require_once '/path/to/oss-sdk/autoload.php';
+
+## 快速使用
+
+### 常用类
+
+| 类名 | 解释 |
+|:------------------|:------------------------------------|
+|OSS\OssClient | OSS客户端类,用户通过OssClient的实例调用接口 |
+|OSS\Core\OssException | OSS异常类,用户在使用的过程中,只需要注意这个异常|
+
+### OssClient初始化
+
+SDK的OSS操作通过OssClient类完成的,下面代码创建一个OssClient对象:
+
+```php
+<?php
+$accessKeyId = "<您从OSS获得的AccessKeyId>"; ;
+$accessKeySecret = "<您从OSS获得的AccessKeySecret>";
+$endpoint = "<您选定的OSS数据中心访问域名,例如oss-cn-hangzhou.aliyuncs.com>";
+try {
+    $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
+} catch (OssException $e) {
+    print $e->getMessage();
+}
+```
+
+### 文件操作
+
+文件(又称对象,Object)是OSS中最基本的数据单元,您可以把它简单地理解为文件,用下面代码可以实现一个Object的上传:
+
+```php
+<?php
+$bucket = "<您使用的Bucket名字,注意命名规范>";
+$object = "<您使用的Object名字,注意命名规范>";
+$content = "Hello, OSS!"; // 上传的文件内容
+try {
+    $ossClient->putObject($bucket, $object, $content);
+} catch (OssException $e) {
+    print $e->getMessage();
+}
+```
+
+### 存储空间操作
+
+存储空间(又称Bucket)是一个用户用来管理所存储Object的存储空间,对于用户来说是一个管理Object的单元,所有的Object都必须隶属于某个Bucket。您可以按照下面的代码新建一个Bucket:
+
+```php
+<?php
+$bucket = "<您使用的Bucket名字,注意命名规范>";
+try {
+    $ossClient->createBucket($bucket);
+} catch (OssException $e) {
+    print $e->getMessage();
+}
+```
+
+### 返回结果处理
+
+OssClient提供的接口返回返回数据分为两种:
+
+* Put,Delete类接口,接口返回null,如果没有OssException,即可认为操作成功
+* Get,List类接口,接口返回对应的数据,如果没有OssException,即可认为操作成功,举个例子:
+
+```php
+<?php
+$bucketListInfo = $ossClient->listBuckets();
+$bucketList = $bucketListInfo->getBucketList();
+foreach($bucketList as $bucket) {
+    print($bucket->getLocation() . "\t" . $bucket->getName() . "\t" . $bucket->getCreateDate() . "\n");
+}
+```
+上面代码中的$bucketListInfo的数据类型是 `OSS\Model\BucketListInfo`
+
+
+### 运行Sample程序
+
+1. 修改 `samples/Config.php`, 补充配置信息
+2. 执行 `cd samples/ && php RunAll.php`
+
+### 运行单元测试
+
+1. 执行`composer install`下载依赖的库
+2. 设置环境变量
+
+        export OSS_ACCESS_KEY_ID=access-key-id
+        export OSS_ACCESS_KEY_SECRET=access-key-secret
+        export OSS_ENDPOINT=endpoint
+        export OSS_BUCKET=bucket-name
+
+3. 执行 `php vendor/bin/phpunit`
+
+## License
+
+- MIT
+
+## 联系我们
+
+- [阿里云OSS官方网站](http://oss.aliyun.com)
+- [阿里云OSS官方论坛](http://bbs.aliyun.com)
+- [阿里云OSS官方文档中心](http://www.aliyun.com/product/oss#Docs)
+- 阿里云官方技术支持:[提交工单](https://workorder.console.aliyun.com/#/ticket/createIndex)
+
+[releases-page]: https://github.com/aliyun/aliyun-oss-php-sdk/releases
+[phar-composer]: https://github.com/clue/phar-composer

+ 155 - 0
vendor/aliyuncs/oss-sdk-php/README.md

@@ -0,0 +1,155 @@
+# Alibaba Cloud OSS SDK for PHP
+
+[![Latest Stable Version](https://poser.pugx.org/aliyuncs/oss-sdk-php/v/stable)](https://packagist.org/packages/aliyuncs/oss-sdk-php)
+[![Build Status](https://travis-ci.org/aliyun/aliyun-oss-php-sdk.svg?branch=master)](https://travis-ci.org/aliyun/aliyun-oss-php-sdk)
+[![Coverage Status](https://coveralls.io/repos/github/aliyun/aliyun-oss-php-sdk/badge.svg?branch=master)](https://coveralls.io/github/aliyun/aliyun-oss-php-sdk?branch=master)
+
+## [README of Chinese](https://github.com/aliyun/aliyun-oss-php-sdk/blob/master/README-CN.md)
+
+## About OSS SDK for PHP V2
+> - OSS SDK for PHP V2([alibabacloud-oss-php-sdk-v2](https://github.com/aliyun/alibabacloud-oss-php-sdk-v2)) beta version has been released, it is a major rewrite of OSS SDK for PHP V1 (aliyun-oss-php-sdk).
+> - V2 simplifies underlying operations such as identification authentication, automatic retry of failed requests, and error handling. It provides flexible parameter configuration methods and rich advanced operations, such as paginator, transmission managers. This comprehensively improves development efficiency and experience.
+
+
+## Overview
+
+Alibaba Cloud Object Storage Service (OSS) is a cloud storage service provided by Alibaba Cloud, featuring a massive capacity, security, a low cost, and high reliability. You can upload and download data on any application anytime and anywhere by calling APIs, and perform simple management of data through the web console. The OSS can store any type of files and therefore applies to various websites, development enterprises and developers.
+
+
+## Run environment
+- PHP 5.3+.
+- cURL extension.
+
+Tips:
+
+- In Ubuntu, you can use the ***apt-get*** package manager to install the *PHP cURL extension*: `sudo apt-get install php5-curl`.
+
+## Install OSS PHP SDK
+
+- If you use the ***composer*** to manage project dependencies, run the following command in your project's root directory:
+
+        composer require aliyuncs/oss-sdk-php
+
+   You can also declare the dependency on Alibaba Cloud OSS SDK for PHP in the `composer.json` file.
+
+        "require": {
+            "aliyuncs/oss-sdk-php": "~2.0"
+        }
+
+   Then run `composer install` to install the dependency. After the Composer Dependency Manager is installed, import the dependency in your PHP code: 
+
+        require_once __DIR__ . '/vendor/autoload.php';
+
+- You can also directly download the packaged [PHAR File][releases-page], and 
+   introduce the file to your code: 
+
+        require_once '/path/to/oss-sdk-php.phar';
+
+- Download the SDK source code, and introduce the `autoload.php` file under the SDK directory to your code: 
+
+        require_once '/path/to/oss-sdk/autoload.php';
+
+## Quick use
+
+### Common classes
+
+| Class | Explanation |
+|:------------------|:------------------------------------|
+|OSS\OssClient | OSS client class. An OssClient instance can be used to call the interface.  |
+|OSS\Core\OssException |OSS Exception class . You only need to pay attention to this exception when you use the OssClient. |
+
+### Initialize an OssClient
+
+The SDK's operations for the OSS are performed through the OssClient class. The code below creates an OssClient object:
+
+```php
+<?php
+$accessKeyId = "<AccessKeyID that you obtain from OSS>";
+$accessKeySecret = "<AccessKeySecret that you obtain from OSS>";
+$endpoint = "<Domain that you select to access an OSS data center, such as "oss-cn-hangzhou.aliyuncs.com>";
+try {
+    $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
+} catch (OssException $e) {
+    print $e->getMessage();
+}
+```
+
+### Operations on objects
+
+Objects are the most basic data units on the OSS. You can simply consider objects as files. The following code uploads an object:
+
+```php
+<?php
+$bucket= "<Name of the bucket in use. Pay attention to naming conventions>";
+$object = "<Name of the object in use. Pay attention to naming conventions>";
+$content = "Hello, OSS!"; // Content of the uploaded file
+try {
+    $ossClient->putObject($bucket, $object, $content);
+} catch (OssException $e) {
+    print $e->getMessage();
+}
+```
+
+### Operations on buckets
+
+Buckets are the space that you use to manage the stored objects. It is an object management unit for users. Each object must belong to a bucket. You can create a bucket with the following code:
+
+```php
+<?php
+$bucket= "<Name of the bucket in use. Pay attention to naming conventions>";
+try {
+    $ossClient->createBucket($bucket);
+} catch (OssException $e) {
+    print $e->getMessage();
+}
+```
+
+### Handle returned results
+
+The OssClient provides the following two types of returned data from interfaces:
+
+- Put and Delete interfaces: The *PUT* and *DELETE* operations are deemed successful if *null* is returned by the interfaces without *OSSException*.
+- Get and List interfaces: The *GET* and *LIST* operations are deemed successful if the desired data is returned by the interfaces without *OSSException*. For example, 
+
+    ```php
+    <?php
+    $bucketListInfo = $ossClient->listBuckets();
+    $bucketList = $bucketListInfo->getBucketList();
+    foreach($bucketList as $bucket) {
+        print($bucket->getLocation() . "\t" . $bucket->getName() . "\t" . $bucket->getCreateDate() . "\n");
+    }
+    ```
+In the above code, $bucketListInfo falls into the 'OSS\Model\BucketListInfo' data type.
+
+
+### Run a sample project
+
+- Modify `samples/Config.php` to complete the configuration information. 
+- Run `cd samples/ && php RunAll.php`. 
+
+### Run a unit test
+
+- Run `composer install` to download the dependent libraries. 
+- Set the environment variable. 
+
+        export OSS_ACCESS_KEY_ID=access-key-id
+        export OSS_ACCESS_KEY_SECRET=access-key-secret
+        export OSS_ENDPOINT=endpoint
+        export OSS_BUCKET=bucket-name
+
+- Run `php vendor/bin/phpunit`
+
+## License
+
+- MIT
+
+## Contact us
+
+- [Alibaba Cloud OSS official website](http://oss.aliyun.com).
+- [Alibaba Cloud OSS official forum](http://bbs.aliyun.com).
+- [Alibaba Cloud OSS official documentation center](http://www.aliyun.com/product/oss#Docs).
+- Alibaba Cloud official technical support: [Submit a ticket](https://workorder.console.aliyun.com/#/ticket/createIndex).
+
+[releases-page]: https://github.com/aliyun/aliyun-oss-php-sdk/releases
+[phar-composer]: https://github.com/clue/phar-composer
+

+ 11 - 0
vendor/aliyuncs/oss-sdk-php/autoload.php

@@ -0,0 +1,11 @@
+<?php
+
+function classLoader($class)
+{
+    $path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
+    $file = __DIR__ . DIRECTORY_SEPARATOR .'src'. DIRECTORY_SEPARATOR . $path . '.php';
+    if (file_exists($file)) {
+        require_once $file;
+    }
+}
+spl_autoload_register('classLoader');

+ 13 - 0
vendor/aliyuncs/oss-sdk-php/build-phar.sh

@@ -0,0 +1,13 @@
+#! /usr/bin/env bash
+
+# Remove dev deps to reduce phar size
+rm -rf composer.lock vendor/
+
+# Generate composer.lock
+composer install --no-dev
+
+# Find SDK version
+version=$(grep 'const OSS_VERSION' src/OSS/OssClient.php | grep -oE '[0-9.]+')
+
+# Build phar
+phar-composer build . aliyun-oss-php-sdk-$version.phar

+ 24 - 0
vendor/aliyuncs/oss-sdk-php/composer.json

@@ -0,0 +1,24 @@
+{
+    "name": "aliyuncs/oss-sdk-php",
+    "description": "Aliyun OSS SDK for PHP",
+    "homepage": "http://www.aliyun.com/product/oss/",
+    "type": "library",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Aliyuncs",
+            "homepage": "http://www.aliyun.com"
+        }
+    ],
+    "require": {
+        "php":">=5.3"
+    },
+    "require-dev" : {
+        "phpunit/phpunit": "*",
+        "php-coveralls/php-coveralls": "*"
+    },
+    "minimum-stability": "stable",
+    "autoload": {
+        "psr-4": {"OSS\\": "src/OSS"}
+    }
+}

BIN
vendor/aliyuncs/oss-sdk-php/example.jpg


+ 3 - 0
vendor/aliyuncs/oss-sdk-php/index.php

@@ -0,0 +1,3 @@
+<?php
+
+require_once __DIR__ . '/vendor/autoload.php';

+ 106 - 0
vendor/aliyuncs/oss-sdk-php/phpunit.xml

@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE xml>
+
+<phpunit>
+	<filter>
+		<whitelist>
+			<directory suffix=".php">./src</directory>
+		</whitelist>
+	</filter>
+	<testsuites>
+		<!-- Unit Tests: 43 files, no OSS credentials required -->
+		<testsuite name="UnitTest">
+			<directory>./tests</directory>
+			<!-- Helper/Base files -->
+			<exclude>./tests/OSS/Tests/Common.php</exclude>
+			<exclude>./tests/OSS/Tests/TestOssClientBase.php</exclude>
+			<exclude>./tests/OSS/Tests/StsClient.php</exclude>
+			<exclude>./tests/OSS/Tests/AssumeRole.php</exclude>
+			<!-- Integration tests: extends TestCase but requires OSS credentials -->
+			<exclude>./tests/OSS/Tests/BucketCnameTest.php</exclude>
+			<exclude>./tests/OSS/Tests/BucketLiveChannelTest.php</exclude>
+			<!-- Integration tests: extends TestOssClientBase -->
+			<exclude>./tests/OSS/Tests/CallbackTest.php</exclude>
+			<exclude>./tests/OSS/Tests/ContentTypeTest.php</exclude>
+			<exclude>./tests/OSS/Tests/ObjectAclTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientAsyncProcessObjectTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketCnameTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketCorsTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketEncryptionTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketInfoTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketLifecycleTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketLoggingTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketPolicyTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketRequestPaymentTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketRefererTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketStatTestTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketStorageCapacityTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketTagsTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketTransferAccelerationTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketVersioningTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketWebsiteTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientBucketWormTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientForcePathStyleTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientImageTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientListObjectsTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientListObjectsV2Test.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientMultipartUploadTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientObjectRequestPaymentTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientObjectTaggingTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientObjectTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientObjectVersioningTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientPresignTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientPresignV4Test.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientRestoreObjectTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientSignatureTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientSignatureV4Test.php</exclude>
+			<exclude>./tests/OSS/Tests/OssClientTest.php</exclude>
+			<exclude>./tests/OSS/Tests/OssTrafficLimitTest.php</exclude>
+			<exclude>./tests/OSS/Tests/SymlinkTest.php</exclude>
+		</testsuite>
+		<!-- Integration Tests: 41 files, requires OSS credentials -->
+		<testsuite name="IntegrationTest">
+			<file>./tests/OSS/Tests/BucketCnameTest.php</file>
+			<file>./tests/OSS/Tests/BucketLiveChannelTest.php</file>
+			<file>./tests/OSS/Tests/CallbackTest.php</file>
+			<file>./tests/OSS/Tests/ContentTypeTest.php</file>
+			<file>./tests/OSS/Tests/ObjectAclTest.php</file>
+			<file>./tests/OSS/Tests/OssClientAsyncProcessObjectTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketCnameTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketCorsTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketEncryptionTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketInfoTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketLifecycleTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketLoggingTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketPolicyTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketRequestPaymentTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketRefererTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketStatTestTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketStorageCapacityTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketTagsTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketTransferAccelerationTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketVersioningTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketWebsiteTest.php</file>
+			<file>./tests/OSS/Tests/OssClientBucketWormTest.php</file>
+			<file>./tests/OSS/Tests/OssClientForcePathStyleTest.php</file>
+			<file>./tests/OSS/Tests/OssClientImageTest.php</file>
+			<file>./tests/OSS/Tests/OssClientListObjectsTest.php</file>
+			<file>./tests/OSS/Tests/OssClientListObjectsV2Test.php</file>
+			<file>./tests/OSS/Tests/OssClientMultipartUploadTest.php</file>
+			<file>./tests/OSS/Tests/OssClientObjectRequestPaymentTest.php</file>
+			<file>./tests/OSS/Tests/OssClientObjectTaggingTest.php</file>
+			<file>./tests/OSS/Tests/OssClientObjectTest.php</file>
+			<file>./tests/OSS/Tests/OssClientObjectVersioningTest.php</file>
+			<file>./tests/OSS/Tests/OssClientPresignTest.php</file>
+			<file>./tests/OSS/Tests/OssClientPresignV4Test.php</file>
+			<file>./tests/OSS/Tests/OssClientRestoreObjectTest.php</file>
+			<file>./tests/OSS/Tests/OssClientSignatureTest.php</file>
+			<file>./tests/OSS/Tests/OssClientSignatureV4Test.php</file>
+			<file>./tests/OSS/Tests/OssClientTest.php</file>
+			<file>./tests/OSS/Tests/OssTrafficLimitTest.php</file>
+			<file>./tests/OSS/Tests/SymlinkTest.php</file>
+		</testsuite>
+	</testsuites>
+</phpunit>

+ 254 - 0
vendor/aliyuncs/oss-sdk-php/samples/Bucket.php

@@ -0,0 +1,254 @@
+<?php
+require_once __DIR__ . '/Common.php';
+
+use OSS\OssClient;
+use OSS\Core\OssException;
+
+$ossClient = Common::getOssClient();
+if (is_null($ossClient)) exit(1);
+$bucket = Common::getBucketName();
+
+//******************************* Simple Usage****************************************************************
+
+// Create a bucket
+$ossClient->createBucket($bucket, OssClient::OSS_ACL_TYPE_PUBLIC_READ_WRITE);
+Common::println("bucket $bucket created");
+
+// Check whether a bucket exists
+$doesExist = $ossClient->doesBucketExist($bucket);
+Common::println("bucket $bucket exist? " . ($doesExist ? "yes" : "no"));
+
+// Get the region of bucket
+$regions = $ossClient->getBucketLocation($bucket);
+Common::println("bucket $bucket region: " .print_r($regions,true));
+
+// Get the meta of a bucket
+$metas  = $ossClient->getBucketMeta($bucket);
+Common::println("bucket $bucket meta: " .print_r($metas,true));
+
+// Get the info of bucket
+$info = $ossClient->getBucketInfo($bucket);
+Common::println("bucket name:".$info->getName()."\n");
+Common::println("bucket location:". $info->getLocation()."\n");
+Common::println("bucket creation time:".$info->getCreateDate()."\n");
+Common::println("bucket storage class:".$info->getStorageClass()."\n");
+Common::println("bucket extranet endpoint:".$info->getExtranetEndpoint()."\n");
+Common::println("bucket intranet endpoint:".$info->getIntranetEndpoint()."\n");
+
+
+// Get the bucket list
+$bucketListInfo = $ossClient->listBuckets();
+
+// Set bucket ACL
+$ossClient->putBucketAcl($bucket, OssClient::OSS_ACL_TYPE_PUBLIC_READ_WRITE);
+Common::println("bucket $bucket acl put");
+// Get bucket ACL
+$acl = $ossClient->getBucketAcl($bucket);
+Common::println("bucket $bucket acl get: " . $acl);
+
+
+//******************************* For complete usage, see the following functions ****************************************************
+
+createBucket($ossClient, $bucket);
+doesBucketExist($ossClient, $bucket);
+getBucketLocation($ossClient, $bucket);
+getBucketMeta($ossClient,$bucket);
+getBucketInfo($ossClient, $bucket);
+deleteBucket($ossClient, $bucket);
+putBucketAcl($ossClient, $bucket);
+getBucketAcl($ossClient, $bucket);
+listBuckets($ossClient);
+
+/**
+ * Create a new bucket
+ * acl indicates the access permission of a bucket, including: private, public-read-only/private-read-write, and public read-write.
+ * Private indicates that only the bucket owner or authorized users can access the data..
+ * The three permissions are separately defined by (OssClient::OSS_ACL_TYPE_PRIVATE,OssClient::OSS_ACL_TYPE_PUBLIC_READ, OssClient::OSS_ACL_TYPE_PUBLIC_READ_WRITE)
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket Name of the bucket to create
+ * @return null
+ */
+function createBucket($ossClient, $bucket)
+{
+    try {
+        $ossClient->createBucket($bucket, OssClient::OSS_ACL_TYPE_PUBLIC_READ_WRITE);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}
+
+/**
+ * Check whether a bucket exists.
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ */
+function doesBucketExist($ossClient, $bucket)
+{
+    try {
+        $res = $ossClient->doesBucketExist($bucket);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    if ($res === true) {
+        print(__FUNCTION__ . ": OK" . "\n");
+    } else {
+        print(__FUNCTION__ . ": FAILED" . "\n");
+    }
+}
+
+/**
+ * Get the info of bucket
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ */
+function getBucketInfo($ossClient, $bucket)
+{
+	try {
+		$info = $ossClient->getBucketInfo($bucket);
+		printf("bucket name:%s\n", $info->getName());
+		printf("bucket location:%s\n", $info->getLocation());
+		printf("bucket creation time:%s\n", $info->getCreateDate());
+		printf("bucket storage class:%s\n", $info->getStorageClass());
+		printf("bucket extranet endpoint:%s\n", $info->getExtranetEndpoint());
+		printf("bucket intranet endpoint:%s\n", $info->getIntranetEndpoint());
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	print(__FUNCTION__ . ": OK" . "\n");
+}
+
+
+/**
+ * Get the meta of a bucket
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ */
+function getBucketLocation($ossClient, $bucket)
+{
+	try {
+		$regions = $ossClient->getBucketLocation($bucket);
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	
+	print("bucket $bucket region: " .print_r($regions,true));
+	
+}
+
+
+/**
+ *  Get the bucket's meta
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ */
+function getBucketMeta($ossClient, $bucket)
+{
+	try {
+		$metas = $ossClient->getBucketMeta($bucket);
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	print(__FUNCTION__ . ": OK" . "\n");
+	print("bucket $bucket meta: " .print_r($metas,true));
+}
+
+/**
+ * Delete a bucket. If the bucket is not empty, the deletion fails.
+ * A bucket which is not empty indicates that it does not contain any objects or parts that are not completely uploaded during multipart upload
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket Name of the bucket to delete
+ * @return null
+ */
+function deleteBucket($ossClient, $bucket)
+{
+    try {
+        $ossClient->deleteBucket($bucket);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}
+
+/**
+ * Set bucket ACL
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function putBucketAcl($ossClient, $bucket)
+{
+    $acl = OssClient::OSS_ACL_TYPE_PRIVATE;
+    try {
+        $ossClient->putBucketAcl($bucket, $acl);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}
+
+
+/**
+ * Get bucket ACL
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function getBucketAcl($ossClient, $bucket)
+{
+    try {
+        $res = $ossClient->getBucketAcl($bucket);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+    print('acl: ' . $res);
+}
+
+
+/**
+ * List all buckets
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @return null
+ */
+function listBuckets($ossClient)
+{
+    $bucketList = null;
+    try {
+        $bucketListInfo = $ossClient->listBuckets();
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+    $bucketList = $bucketListInfo->getBucketList();
+    foreach ($bucketList as $bucket) {
+        print($bucket->getLocation() . "\t" . $bucket->getName() . "\t" . $bucket->getCreatedate() . "\n");
+    }
+}

+ 91 - 0
vendor/aliyuncs/oss-sdk-php/samples/BucketCname.php

@@ -0,0 +1,91 @@
+<?php
+require_once __DIR__ . '/Common.php';
+
+use OSS\OssClient;
+use OSS\Core\OssException;
+
+$bucket = Common::getBucketName();
+$ossClient = Common::getOssClient();
+if (is_null($ossClient)) exit(1);
+
+//*******************************Simple Usage ***************************************************************
+
+// Add Canme record
+$myDomain = '<yourDomainName>';
+$ossClient->addBucketCname($bucket, $myDomain);
+
+// View cname records
+$cnameConfig = $ossClient->getBucketCname($bucket);
+Common::println("bucket $bucket cname:" . $cnameConfig->serializeToXml());
+
+// Delete bucket cname
+$myDomain = '<yourDomainName>';
+$ossClient->deleteBucketCname($bucket,$myDomain);
+Common::println("bucket $bucket cname deleted");
+
+//******************************* For complete usage, see the following functions ****************************************************
+
+addBucketCname($ossClient, $bucket);
+getBucketCname($ossClient, $bucket);
+deleteBucketCname($ossClient, $bucket);
+
+/**
+ * Set bucket cname
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function addBucketCname($ossClient, $bucket)
+{
+	// Set up a custom domain name.
+	$myDomain = '<yourDomainName>';
+	try {
+		$ossClient->addBucketCname($bucket, $myDomain);
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	print(__FUNCTION__ . ": OK" . "\n");
+}
+
+/**
+ * Get bucket cname
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function getBucketCname($ossClient, $bucket)
+{
+    try {
+		$cnameConfig = $ossClient->getBucketCname($bucket);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+    print($cnameConfig->serializeToXml() . "\n");
+}
+
+/**
+ * Delete bucket cname
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function deleteBucketCname($ossClient, $bucket)
+{
+	$myDomain = '<yourDomainName>';
+    try {
+		$ossClient->deleteBucketCname($bucket, $myDomain);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}

+ 171 - 0
vendor/aliyuncs/oss-sdk-php/samples/BucketCors.php

@@ -0,0 +1,171 @@
+<?php
+require_once __DIR__ . '/Common.php';
+
+use OSS\OssClient;
+use OSS\Core\OssException;
+use OSS\Model\CorsConfig;
+use OSS\Model\CorsRule;
+
+$ossClient = Common::getOssClient();
+if (is_null($ossClient)) exit(1);
+$bucket = Common::getBucketName();
+
+
+//******************************* Simple usage****************************************************************
+
+// Set cors configuration
+$corsConfig = new CorsConfig();
+$rule = new CorsRule();
+$rule->addAllowedHeader("x-oss-header");
+$rule->addAllowedOrigin("http://www.b.com");
+$rule->addAllowedMethod("POST");
+$rule->setMaxAgeSeconds(10);
+$corsConfig->addRule($rule);
+$ossClient->putBucketCors($bucket, $corsConfig);
+Common::println("bucket $bucket corsConfig created:" . $corsConfig->serializeToXml());
+
+// Get cors configuration
+$corsConfig = $ossClient->getBucketCors($bucket);
+
+if ($corsConfig->getResponseVary()){
+    printf("Response Vary : true" .PHP_EOL);
+}else{
+    printf("Response Vary : false" .PHP_EOL);
+}
+
+foreach ($corsConfig->getRules() as $key => $rule){
+    if($rule->getAllowedHeaders()){
+        foreach($rule->getAllowedHeaders() as $header){
+            printf("Allowed Headers :" .$header .PHP_EOL);
+        }
+    }
+    if ($rule->getAllowedMethods()){
+        foreach($rule->getAllowedMethods() as $method){
+            printf("Allowed Methods :" .$method . PHP_EOL);
+        }
+
+    }
+    if($rule->getAllowedOrigins()){
+        foreach($rule->getAllowedOrigins() as $origin){
+            printf("Allowed Origins :" .$origin , PHP_EOL);
+        }
+
+    }
+    if($rule->getExposeHeaders()){
+        foreach($rule->getExposeHeaders() as $exposeHeader){
+            printf("Expose Headers :" .$exposeHeader . PHP_EOL);
+        }
+    }
+    printf("Max Age Seconds :" .$rule->getMaxAgeSeconds() .PHP_EOL);
+
+}
+
+// Delete cors configuration
+$ossClient->deleteBucketCors($bucket);
+Common::println("bucket $bucket corsConfig deleted");
+
+//******************************* For complete usage, see the following functions  *****************************************************
+
+putBucketCors($ossClient, $bucket);
+getBucketCors($ossClient, $bucket);
+deleteBucketCors($ossClient, $bucket);
+getBucketCors($ossClient, $bucket);
+
+/**
+ * Set bucket cores
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function putBucketCors($ossClient, $bucket)
+{
+    $corsConfig = new CorsConfig();
+    $rule = new CorsRule();
+    $rule->addAllowedHeader("x-oss-header");
+    $rule->addAllowedOrigin("http://www.b.com");
+    $rule->addAllowedMethod("POST");
+    $rule->setMaxAgeSeconds(10);
+    $corsConfig->addRule($rule);
+
+    try {
+        $ossClient->putBucketCors($bucket, $corsConfig);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}
+
+/**
+ * Get and print the cors configuration of a bucket
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function getBucketCors($ossClient, $bucket)
+{
+    $corsConfig = null;
+    try {
+        $corsConfig = $ossClient->getBucketCors($bucket);
+
+        if ($corsConfig->getResponseVary()){
+            printf("Response Vary : true" .PHP_EOL);
+        }else{
+            printf("Response Vary : false" .PHP_EOL);
+        }
+        foreach ($corsConfig->getRules() as $key => $rule){
+            if($rule->getAllowedHeaders()){
+                foreach($rule->getAllowedHeaders() as $header){
+                    printf("Allowed Headers :" .$header .PHP_EOL);
+                }
+            }
+            if ($rule->getAllowedMethods()){
+                foreach($rule->getAllowedMethods() as $method){
+                    printf("Allowed Methods :" .$method . PHP_EOL);
+                }
+
+            }
+            if($rule->getAllowedOrigins()){
+                foreach($rule->getAllowedOrigins() as $origin){
+                    printf("Allowed Origins :" .$origin , PHP_EOL);
+                }
+
+            }
+            if($rule->getExposeHeaders()){
+                foreach($rule->getExposeHeaders() as $exposeHeader){
+                    printf("Expose Headers :" .$exposeHeader . PHP_EOL);
+                }
+            }
+            printf("Max Age Seconds :" .$rule->getMaxAgeSeconds() .PHP_EOL);
+
+        }
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}
+
+/**
+ * Delete all cors configuraiton of a bucket
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function deleteBucketCors($ossClient, $bucket)
+{
+    try {
+        $ossClient->deleteBucketCors($bucket);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}
+

+ 98 - 0
vendor/aliyuncs/oss-sdk-php/samples/BucketEncryption.php

@@ -0,0 +1,98 @@
+<?php
+
+require_once __DIR__ . '/Common.php';
+
+use OSS\OssClient;
+use OSS\Core\OssException;
+use OSS\Model\ServerSideEncryptionConfig;
+
+$ossClient = Common::getOssClient();
+if (is_null($ossClient)) exit(1);
+$bucket = Common::getBucketName();
+
+//******************************* Simple Usage****************************************************************
+
+// Configure Bucket encryption
+// Set Bucket's default server-side encryption method to OSS fully managed encryption (SSE-OSS).
+$config = new ServerSideEncryptionConfig("AES256");
+// Set Bucket's default server-side encryption method to KMS, and do not specify a CMK ID.
+//$config = new ServerSideEncryptionConfig("KMS");
+// Set Bucket's default server-side encryption method to KMS, and specify the CMK ID.
+//$config = new ServerSideEncryptionConfig("KMS", "your kms id");
+$ossClient->putBucketEncryption($bucket, $config);
+Common::println("bucket $bucket encryoption created");
+
+$config = $ossClient->getBucketEncryption($bucket);
+Common::println("bucket $bucket encryoption:".$config->serializeToXml());
+
+$config = $ossClient->deleteBucketEncryption($bucket);
+Common::println("bucket $bucket encryoption has deleted");
+
+//******************************* For complete usage, see the following functions ****************************************************
+putBucketEncryption($ossClient, $bucket);
+getBucketEncryption($ossClient, $bucket);
+deleteBucketEncryption($ossClient, $bucket);
+
+/**
+ * Configure Bucket encryption
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket Name of the bucket to create
+ * @return null
+ */
+
+function putBucketEncryption($ossClient,$bucket){
+	try {
+		// Set Bucket's default server-side encryption method to OSS fully managed encryption (SSE-OSS).
+		$config = new ServerSideEncryptionConfig("AES256");
+		// Set Bucket's default server-side encryption method to KMS, and do not specify a CMK ID.
+		//$config = new ServerSideEncryptionConfig("KMS");
+		// Set Bucket's default server-side encryption method to KMS, and specify the CMK ID.
+		//$config = new ServerSideEncryptionConfig("KMS", "your kms id");
+		$ossClient->putBucketEncryption($bucket, $config);
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	print(__FUNCTION__ . ": OK" . "\n");
+}
+
+/**
+ * Get Bucket encryption
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket Name of the bucket to create
+ * @return null
+ */
+
+function getBucketEncryption($ossClient,$bucket){
+	try {
+		$config = $ossClient->getBucketEncryption($bucket);
+		print($config->getSSEAlgorithm());
+		print($config->getKMSMasterKeyID());
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	print(__FUNCTION__ . ": OK" . "\n");
+}
+
+
+/**
+ * Delete Bucket encryption
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket Name of the bucket to create
+ * @return null
+ */
+
+function deleteBucketEncryption($ossClient,$bucket){
+	try {
+		$ossClient->deleteBucketEncryption($bucket);
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	print(__FUNCTION__ . ": OK" . "\n");
+}
+

+ 109 - 0
vendor/aliyuncs/oss-sdk-php/samples/BucketLifecycle.php

@@ -0,0 +1,109 @@
+<?php
+require_once __DIR__ . '/Common.php';
+
+use OSS\OssClient;
+use OSS\Core\OssException;
+use OSS\Model\LifecycleAction;
+use OSS\Model\LifecycleConfig;
+use OSS\Model\LifecycleRule;
+
+$bucket = Common::getBucketName();
+$ossClient = Common::getOssClient();
+if (is_null($ossClient)) exit(1);
+
+//******************************* Simple Usage *******************************************************
+
+// Set lifecycle configuration
+$lifecycleConfig = new LifecycleConfig();
+$actions = array();
+$actions[] = new LifecycleAction("Expiration", "Days", 3);
+$lifecycleRule = new LifecycleRule("delete obsoleted files", "obsoleted/", "Enabled", $actions);
+$lifecycleConfig->addRule($lifecycleRule);
+$ossClient->putBucketLifecycle($bucket, $lifecycleConfig);
+Common::println("bucket $bucket lifecycleConfig created:" . $lifecycleConfig->serializeToXml());
+
+// Get lifecycle configuration
+$lifecycleConfig = $ossClient->getBucketLifecycle($bucket);
+Common::println("bucket $bucket lifecycleConfig fetched:" . $lifecycleConfig->serializeToXml());
+
+// Delete bucket lifecycle configuration
+$ossClient->deleteBucketLifecycle($bucket);
+Common::println("bucket $bucket lifecycleConfig deleted");
+
+
+//***************************** For complete usage, see the following functions  ***********************************************
+
+putBucketLifecycle($ossClient, $bucket);
+getBucketLifecycle($ossClient, $bucket);
+deleteBucketLifecycle($ossClient, $bucket);
+getBucketLifecycle($ossClient, $bucket);
+
+/**
+ * Set bucket lifecycle configuration
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function putBucketLifecycle($ossClient, $bucket)
+{
+    $lifecycleConfig = new LifecycleConfig();
+    $actions = array();
+    $actions[] = new LifecycleAction(OssClient::OSS_LIFECYCLE_EXPIRATION, OssClient::OSS_LIFECYCLE_TIMING_DAYS, 3);
+    $lifecycleRule = new LifecycleRule("delete obsoleted files", "obsoleted/", "Enabled", $actions);
+    $lifecycleConfig->addRule($lifecycleRule);
+    $actions = array();
+    $actions[] = new LifecycleAction(OssClient::OSS_LIFECYCLE_EXPIRATION, OssClient::OSS_LIFECYCLE_TIMING_DATE, '2022-10-12T00:00:00.000Z');
+    $lifecycleRule = new LifecycleRule("delete temporary files", "temporary/", "Enabled", $actions);
+    $lifecycleConfig->addRule($lifecycleRule);
+    try {
+        $ossClient->putBucketLifecycle($bucket, $lifecycleConfig);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}
+
+/**
+ * Get bucket lifecycle configuration
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function getBucketLifecycle($ossClient, $bucket)
+{
+    $lifecycleConfig = null;
+    try {
+        $lifecycleConfig = $ossClient->getBucketLifecycle($bucket);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+    print($lifecycleConfig->serializeToXml() . "\n");
+}
+
+/**
+ * Delete bucket lifecycle configuration
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function deleteBucketLifecycle($ossClient, $bucket)
+{
+    try {
+        $ossClient->deleteBucketLifecycle($bucket);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}
+
+

+ 95 - 0
vendor/aliyuncs/oss-sdk-php/samples/BucketLogging.php

@@ -0,0 +1,95 @@
+<?php
+require_once __DIR__ . '/Common.php';
+
+use OSS\OssClient;
+use OSS\Core\OssException;
+
+$bucket = Common::getBucketName();
+$ossClient = Common::getOssClient();
+if (is_null($ossClient)) exit(1);
+
+//*******************************Simple Usage ***************************************************************
+
+// Set bucket access logging rules. Access logs are stored under the same bucket with a 'access.log' prefix.
+$ossClient->putBucketLogging($bucket, $bucket, "access.log", array());
+Common::println("bucket $bucket lifecycleConfig created");
+
+// Get bucket access logging rules
+$loggingConfig = $ossClient->getBucketLogging($bucket, array());
+Common::println("bucket $bucket lifecycleConfig fetched:" . $loggingConfig->serializeToXml());
+
+// Delete bucket access logging rules
+$loggingConfig = $ossClient->getBucketLogging($bucket, array());
+Common::println("bucket $bucket lifecycleConfig deleted");
+
+//******************************* For complete usage, see the following functions ****************************************************
+
+putBucketLogging($ossClient, $bucket);
+getBucketLogging($ossClient, $bucket);
+deleteBucketLogging($ossClient, $bucket);
+getBucketLogging($ossClient, $bucket);
+
+/**
+ * Set bucket logging configuration
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function putBucketLogging($ossClient, $bucket)
+{
+    $option = array();
+    // Access logs are stored in the same bucket.
+    $targetBucket = $bucket;
+    $targetPrefix = "access.log";
+
+    try {
+        $ossClient->putBucketLogging($bucket, $targetBucket, $targetPrefix, $option);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}
+
+/**
+ * Get bucket logging configuration
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function getBucketLogging($ossClient, $bucket)
+{
+    $loggingConfig = null;
+    $options = array();
+    try {
+        $loggingConfig = $ossClient->getBucketLogging($bucket, $options);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+    print($loggingConfig->serializeToXml() . "\n");
+}
+
+/**
+ * Delete bucket logging configuration
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function deleteBucketLogging($ossClient, $bucket)
+{
+    try {
+        $ossClient->deleteBucketLogging($bucket);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}

+ 116 - 0
vendor/aliyuncs/oss-sdk-php/samples/BucketPayment.php

@@ -0,0 +1,116 @@
+<?php
+require_once __DIR__ . '/Common.php';
+
+use OSS\OssClient;
+use OSS\Core\OssException;
+
+$ossClient = Common::getOssClient();
+if (is_null($ossClient)) exit(1);
+$bucket = Common::getBucketName();
+
+//******************************* Simple Usage****************************************************************
+
+//Set requester payment mode
+$ossClient->putBucketRequestPayment($bucket, "Requester");
+
+//Get requester payment mode configuration
+$payer = $ossClient->getBucketRequestPayment($bucket);
+Common::println("bucket $bucket Payer:".$payer.PHP_EOL);
+
+//Third-party paid access to Object
+$options = array(
+	OssClient::OSS_HEADERS => array(
+		OssClient::OSS_REQUEST_PAYER => 'requester',
+	));
+
+$content = "hello";
+$object = "object";
+
+//PutObject interface to specify the payer
+$ossClient->putObject($bucket, $object, $content, $options);
+
+// GetObject interface to specify the payer
+$ossClient->getObject($bucket, $object, $options);
+
+// DeleteObject interface to specify the payer
+$ossClient->deleteObject($bucket, $object, $options);
+
+//******************************* For complete usage, see the following functions ****************************************************
+
+putBucketRequestPayment($ossClient,$bucket);
+getBucketRequestPayment($ossClient,$bucket);
+setObjectPayment($ossClient,$bucket);
+
+/**
+ * Set requester payment mode
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket Name of the bucket to create
+ * @return null
+ */
+function putBucketRequestPayment($ossClient, $bucket)
+{
+	try {
+		$ossClient->putBucketRequestPayment($bucket, "Requester");
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	
+	print(__FUNCTION__ . ": OK" . "\n");
+}
+
+
+/**
+ * Get payment mode of bucket
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket Name of the bucket to create
+ * @return null
+ */
+function getBucketRequestPayment($ossClient, $bucket)
+{
+	try {
+		$payer = $ossClient->getBucketRequestPayment($bucket);
+		print("bucket $bucket Payer:".$payer.PHP_EOL);
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	
+	print(__FUNCTION__ . ": OK" . "\n");
+}
+
+/**
+ * Set payment mode of object
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket Name of the bucket to create
+ * @return null
+ */
+function setObjectPayment($ossClient,$bucket){
+	// Specify the payment model for the requester.
+	$options = array(
+		OssClient::OSS_HEADERS => array(
+			OssClient::OSS_REQUEST_PAYER => 'requester',
+		));
+	
+	try {
+		
+		$content = "hello";
+		$object = "object";
+		//PutObject interface to specify the payer
+		$ossClient->putObject($bucket, $object, $content, $options);
+		// GetObject interface to specify the payer
+		$ossClient->getObject($bucket, $object, $options);
+		// DeleteObject interface to specify the payer
+		$ossClient->deleteObject($bucket, $object, $options);
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	
+	print(__FUNCTION__ . ": OK" . "\n");
+}
+
+

+ 123 - 0
vendor/aliyuncs/oss-sdk-php/samples/BucketPolicy.php

@@ -0,0 +1,123 @@
+<?php
+require_once __DIR__ . '/Common.php';
+
+use OSS\OssClient;
+use OSS\Core\OssException;
+
+$ossClient = Common::getOssClient();
+if (is_null($ossClient)) exit(1);
+$bucket = Common::getBucketName();
+
+//******************************* Simple Usage****************************************************************
+
+// Set Bucket Policy
+// Authorization strategy.
+$policy = <<< BBBB
+{
+  "Version":"1",
+  "Statement":[
+  {
+    "Action":[
+    "oss:PutObject",
+    "oss:GetObject"
+  ],
+    "Effect":"Allow",
+    "Resource":["acs:oss:*:*:*/user1/*"]
+  }
+  ]
+}
+BBBB;
+$ossClient->putBucketPolicy($bucket, $policy);
+
+// Get bucket pllicy
+$policy = $ossClient->getBucketPolicy($bucket);
+Common::println("bucket $bucket policy: " . $policy);
+
+
+// Delete bucket pllicy
+$policy = $ossClient->deleteBucketPolicy($bucket);
+
+//******************************* For complete usage, see the following functions ****************************************************
+
+putBucketPolicy($ossClient, $bucket);
+getBucketPolicy($ossClient, $bucket);
+deleteBucketPolicy($ossClient, $bucket);
+
+/**
+ * Set Bucket Policy
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket Name of the bucket to create
+ * @return null
+ */
+function putBucketPolicy($ossClient, $bucket)
+{
+	$policy = <<< BBBB
+{
+  "Version":"1",
+  "Statement":[
+  {
+    "Action":[
+    "oss:PutObject",
+    "oss:GetObject"
+  ],
+    "Effect":"Allow",
+    "Resource":["acs:oss:*:*:*/user1/*"]
+  }
+  ]
+}
+BBBB;
+	
+	try {
+		$ossClient->putBucketPolicy($bucket, $policy);
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	
+	print(__FUNCTION__ . ": OK" . "\n");
+}
+
+
+/**
+ * Get Bucket Policy
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket Name of the bucket to create
+ * @return null
+ */
+function getBucketPolicy($ossClient, $bucket)
+{
+	try {
+		$policy = $ossClient->getBucketPolicy($bucket);
+		print($policy);
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	
+	print(__FUNCTION__ . ": OK" . "\n");
+}
+
+
+/**
+ * Delete Bucket Policy
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket Name of the bucket to create
+ * @return null
+ */
+function deleteBucketPolicy($ossClient, $bucket)
+{
+	try {
+		$ossClient->deleteBucketPolicy($bucket);
+	} catch (OssException $e) {
+		printf(__FUNCTION__ . ": FAILED\n");
+		printf($e->getMessage() . "\n");
+		return;
+	}
+	
+	print(__FUNCTION__ . ": OK" . "\n");
+}

+ 101 - 0
vendor/aliyuncs/oss-sdk-php/samples/BucketReferer.php

@@ -0,0 +1,101 @@
+<?php
+require_once __DIR__ . '/Common.php';
+
+use OSS\OssClient;
+use OSS\Core\OssException;
+use \OSS\Model\RefererConfig;
+
+$bucket = Common::getBucketName();
+$ossClient = Common::getOssClient();
+if (is_null($ossClient)) exit(1);
+
+//******************************* Simple Usage ****************************************************************
+
+// Set referer whitelist
+$refererConfig = new RefererConfig();
+$refererConfig->setAllowEmptyReferer(true);
+$refererConfig->addReferer("www.aliiyun.com");
+$refererConfig->addReferer("www.aliiyuncs.com");
+$ossClient->putBucketReferer($bucket, $refererConfig);
+Common::println("bucket $bucket refererConfig created:" . $refererConfig->serializeToXml());
+// Get referer whitelist
+$refererConfig = $ossClient->getBucketReferer($bucket);
+Common::println("bucket $bucket refererConfig fetched:" . $refererConfig->serializeToXml());
+
+// Delete referrer whitelist
+$refererConfig = new RefererConfig();
+$ossClient->putBucketReferer($bucket, $refererConfig);
+Common::println("bucket $bucket refererConfig deleted");
+
+
+//******************************* For complete usage, see the following functions ****************************************************
+
+putBucketReferer($ossClient, $bucket);
+getBucketReferer($ossClient, $bucket);
+deleteBucketReferer($ossClient, $bucket);
+getBucketReferer($ossClient, $bucket);
+
+/**
+ * Set bucket referer configuration
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function putBucketReferer($ossClient, $bucket)
+{
+    $refererConfig = new RefererConfig();
+    $refererConfig->setAllowEmptyReferer(true);
+    $refererConfig->addReferer("www.aliiyun.com");
+    $refererConfig->addReferer("www.aliiyuncs.com");
+    try {
+        $ossClient->putBucketReferer($bucket, $refererConfig);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}
+
+/**
+ * Get bucket referer configuration
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function getBucketReferer($ossClient, $bucket)
+{
+    $refererConfig = null;
+    try {
+        $refererConfig = $ossClient->getBucketReferer($bucket);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+    print($refererConfig->serializeToXml() . "\n");
+}
+
+/**
+ * Delete bucket referer configuration
+ * Referer whitelist cannot be directly deleted. So use a empty one to overwrite it.
+ *
+ * @param OssClient $ossClient OssClient instance
+ * @param string $bucket bucket name
+ * @return null
+ */
+function deleteBucketReferer($ossClient, $bucket)
+{
+    $refererConfig = new RefererConfig();
+    try {
+        $ossClient->putBucketReferer($bucket, $refererConfig);
+    } catch (OssException $e) {
+        printf(__FUNCTION__ . ": FAILED\n");
+        printf($e->getMessage() . "\n");
+        return;
+    }
+    print(__FUNCTION__ . ": OK" . "\n");
+}

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác