Quellcode durchsuchen

安装tp6-captcha扩展

Yahoo vor 4 Jahren
Ursprung
Commit
2d87f5ea6f
50 geänderte Dateien mit 2831 neuen und 37 gelöschten Zeilen
  1. 4 2
      app/api/config/captcha.php
  2. 1 1
      app/api/model/User.php
  3. 4 3
      app/api/service/passport/Captcha.php
  4. 15 16
      app/api/service/passport/Login.php
  5. 4 4
      app/api/service/passport/SmsCaptcha.php
  6. 2 1
      composer.json
  7. 94 1
      composer.lock
  8. 2 6
      config/captcha.php
  9. 2 0
      vendor/composer/autoload_psr4.php
  10. 13 0
      vendor/composer/autoload_static.php
  11. 99 0
      vendor/composer/installed.json
  12. 20 2
      vendor/composer/installed.php
  13. 1 1
      vendor/services.php
  14. 5 0
      vendor/yiovo/tp6-cache/.gitignore
  15. 191 0
      vendor/yiovo/tp6-cache/LICENSE
  16. 11 0
      vendor/yiovo/tp6-cache/README.md
  17. 21 0
      vendor/yiovo/tp6-cache/composer.json
  18. 198 0
      vendor/yiovo/tp6-cache/src/Cache.php
  19. 357 0
      vendor/yiovo/tp6-cache/src/cache/Driver.php
  20. 132 0
      vendor/yiovo/tp6-cache/src/cache/TagSet.php
  21. 342 0
      vendor/yiovo/tp6-cache/src/cache/driver/File.php
  22. 209 0
      vendor/yiovo/tp6-cache/src/cache/driver/Memcache.php
  23. 221 0
      vendor/yiovo/tp6-cache/src/cache/driver/Memcached.php
  24. 277 0
      vendor/yiovo/tp6-cache/src/cache/driver/Redis.php
  25. 175 0
      vendor/yiovo/tp6-cache/src/cache/driver/Wincache.php
  26. 50 0
      vendor/yiovo/tp6-cache/src/facade/Cache.php
  27. 5 0
      vendor/yiovo/tp6-captcha/.gitignore
  28. 191 0
      vendor/yiovo/tp6-captcha/LICENSE
  29. 3 0
      vendor/yiovo/tp6-captcha/README.md
  30. BIN
      vendor/yiovo/tp6-captcha/assets/bgs/1.jpg
  31. BIN
      vendor/yiovo/tp6-captcha/assets/bgs/2.jpg
  32. BIN
      vendor/yiovo/tp6-captcha/assets/bgs/3.jpg
  33. BIN
      vendor/yiovo/tp6-captcha/assets/bgs/4.jpg
  34. BIN
      vendor/yiovo/tp6-captcha/assets/bgs/5.jpg
  35. BIN
      vendor/yiovo/tp6-captcha/assets/bgs/6.jpg
  36. BIN
      vendor/yiovo/tp6-captcha/assets/bgs/7.jpg
  37. BIN
      vendor/yiovo/tp6-captcha/assets/bgs/8.jpg
  38. BIN
      vendor/yiovo/tp6-captcha/assets/ttfs/1.ttf
  39. BIN
      vendor/yiovo/tp6-captcha/assets/ttfs/2.ttf
  40. BIN
      vendor/yiovo/tp6-captcha/assets/ttfs/3.ttf
  41. BIN
      vendor/yiovo/tp6-captcha/assets/ttfs/4.ttf
  42. BIN
      vendor/yiovo/tp6-captcha/assets/ttfs/5.ttf
  43. BIN
      vendor/yiovo/tp6-captcha/assets/ttfs/6.ttf
  44. BIN
      vendor/yiovo/tp6-captcha/assets/zhttfs/1.ttf
  45. 31 0
      vendor/yiovo/tp6-captcha/composer.json
  46. 42 0
      vendor/yiovo/tp6-captcha/src/Captcha.php
  47. 32 0
      vendor/yiovo/tp6-captcha/src/CaptchaApi.php
  48. 35 0
      vendor/yiovo/tp6-captcha/src/config.php
  49. 20 0
      vendor/yiovo/tp6-captcha/src/facade/Captcha.php
  50. 22 0
      vendor/yiovo/tp6-captcha/src/facade/CaptchaApi.php

+ 4 - 2
app/api/config/captcha.php

@@ -8,7 +8,7 @@
 // +----------------------------------------------------------------------
 // | Author: 萤火科技 <admin@yiovo.com>
 // +----------------------------------------------------------------------
-declare (strict_types = 1);
+declare (strict_types=1);
 
 return [
     // 验证码图片宽度
@@ -25,5 +25,7 @@ return [
     'fontSize' => 26,
     // 验证码字符集合
     // 复杂版:2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY
-    'codeSet' => '23456ACEFHJKLMNPRTUVWXY'
+    'codeSet' => '23456ACEFHJKLMNPRTUVWXY',
+    // 验证码可重复验证的次数
+    'checkTimes' => 5,
 ];

+ 1 - 1
app/api/model/User.php

@@ -13,7 +13,7 @@ declare (strict_types=1);
 namespace app\api\model;
 
 use think\facade\Cache;
-use edward\captcha\facade\CaptchaApi;
+use yiovo\captcha\facade\CaptchaApi;
 use app\api\service\User as UserService;
 use app\common\model\User as UserModel;
 use cores\exception\BaseException;

+ 4 - 3
app/api/service/passport/Captcha.php

@@ -13,15 +13,16 @@ declare (strict_types = 1);
 namespace app\api\service\passport;
 
 use app\common\service\BaseService;
-use edward\captcha\facade\CaptchaApi;
+use yiovo\captcha\facade\CaptchaApi;
+use think\response\Json;
 
 class Captcha extends BaseService
 {
     /**
      * 图形验证码
-     * @return array|\think\response\Json
+     * @return array
      */
-    public function create()
+    public function create(): array
     {
         $data = CaptchaApi::create();
         return [

+ 15 - 16
app/api/service/passport/Login.php

@@ -16,9 +16,9 @@ use app\api\model\User as UserModel;
 use app\api\service\user\Oauth as OauthService;
 use app\api\service\user\Avatar as AvatarService;
 use app\api\validate\passport\Login as ValidateLogin;
-use app\common\exception\BaseException;
+use cores\exception\BaseException;
 use app\common\service\BaseService;
-use edward\captcha\facade\CaptchaApi;
+use yiovo\captcha\facade\CaptchaApi;
 use think\facade\Cache;
 
 /**
@@ -43,7 +43,7 @@ class Login extends BaseService
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
      */
-    public function login(array $data)
+    public function login(array $data): bool
     {
         // 数据验证
         if (!$this->validate($data)) {
@@ -66,7 +66,7 @@ class Login extends BaseService
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
      */
-    public function mpWxLogin(array $data)
+    public function mpWxLogin(array $data): bool
     {
         try {
             // 根据code换取openid
@@ -99,7 +99,7 @@ class Login extends BaseService
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
      */
-    private function oauth(array $data)
+    private function oauth(array $data): bool
     {
         if ($data['isParty']) {
             $Oauth = new OauthService;
@@ -112,7 +112,7 @@ class Login extends BaseService
      * 当前登录的用户信息
      * @return array
      */
-    public function getUserInfo()
+    public function getUserInfo(): array
     {
         return $this->userInfo;
     }
@@ -122,7 +122,7 @@ class Login extends BaseService
      * @param array $data
      * @return bool
      */
-    private function register(array $data)
+    private function register(array $data): bool
     {
         // 查询用户是否已存在
         $userInfo = UserModel::detail(['mobile' => $data['mobile']]);
@@ -142,7 +142,7 @@ class Login extends BaseService
      * @param array $partyData 用户信息(第三方)
      * @return bool
      */
-    private function createUser(string $mobile, bool $isParty, array $partyData = [])
+    private function createUser(string $mobile, bool $isParty, array $partyData = []): bool
     {
         // 用户信息
         $data = [
@@ -171,7 +171,7 @@ class Login extends BaseService
      * @param bool $isGetAvatarUrl 是否下载头像
      * @return array
      */
-    private function partyUserInfo(array $partyData, bool $isGetAvatarUrl = true)
+    private function partyUserInfo(array $partyData, bool $isGetAvatarUrl = true): array
     {
         $partyUserInfo = $partyData['userInfo'];
         $data = [
@@ -190,7 +190,7 @@ class Login extends BaseService
      * @param string $avatarUrl
      * @return int
      */
-    private function partyAvatar(string $avatarUrl)
+    private function partyAvatar(string $avatarUrl): int
     {
         $Avatar = new AvatarService;
         $fileId = $Avatar->party($avatarUrl);
@@ -204,7 +204,7 @@ class Login extends BaseService
      * @param array $partyData 用户信息(第三方)
      * @return bool
      */
-    private function updateUser(UserModel $userInfo, bool $isParty, array $partyData = [])
+    private function updateUser(UserModel $userInfo, bool $isParty, array $partyData = []): bool
     {
         // 用户信息
         $data = [
@@ -228,7 +228,7 @@ class Login extends BaseService
      * @return bool
      * @throws BaseException
      */
-    private function session()
+    private function session(): bool
     {
         empty($this->userInfo) && throwError('未找到用户信息');
         // 登录的token
@@ -247,7 +247,7 @@ class Login extends BaseService
      * @param array $data
      * @return bool
      */
-    private function validate(array $data)
+    private function validate(array $data): bool
     {
         // 数据验证
         $validate = new ValidateLogin;
@@ -268,7 +268,7 @@ class Login extends BaseService
      * @param int $userId
      * @return string
      */
-    public function getToken(int $userId)
+    public function getToken(int $userId): string
     {
         static $token = '';
         if (empty($token)) {
@@ -282,7 +282,7 @@ class Login extends BaseService
      * @param int $userId
      * @return string
      */
-    public function makeToken(int $userId)
+    public function makeToken(int $userId): string
     {
         $storeId = $this->storeId;
         // 生成一个不会重复的随机字符串
@@ -293,5 +293,4 @@ class Login extends BaseService
         $salt = self::TOKEN_SALT;
         return md5("{$storeId}_{$timeStamp}_{$userId}_{$guid}_{$salt}");
     }
-
 }

+ 4 - 4
app/api/service/passport/SmsCaptcha.php

@@ -15,7 +15,7 @@ namespace app\api\service\passport;
 use app\api\validate\passport\SmsCaptcha as ValidateSmsCaptcha;
 use app\common\service\BaseService;
 use app\common\service\Message as MessageService;
-use edward\captcha\facade\CaptchaApi;
+use yiovo\captcha\facade\CaptchaApi;
 
 /**
  * 服务类:发送短信验证码
@@ -29,7 +29,7 @@ class SmsCaptcha extends BaseService
      * @param array $data
      * @return bool
      */
-    public function sendSmsCaptcha(array $data)
+    public function sendSmsCaptcha(array $data): bool
     {
         // 数据验证
         if (!$this->validate($data)) return false;
@@ -52,7 +52,7 @@ class SmsCaptcha extends BaseService
      * @param array $data
      * @return bool
      */
-    private function validate(array $data)
+    private function validate(array $data): bool
     {
         // 数据验证
         $validate = new ValidateSmsCaptcha;
@@ -62,7 +62,7 @@ class SmsCaptcha extends BaseService
         }
         // 验证图形验证码
         if (!CaptchaApi::check($data['captchaCode'], $data['captchaKey'])) {
-            $this->error = '图形验证码不正确';
+            $this->error = '很抱歉,图形验证码不正确';
             return false;
         }
         return true;

+ 2 - 1
composer.json

@@ -41,7 +41,8 @@
         "myclabs/php-enum": "^1.6",
         "lvht/geohash": "^1.1",
         "phpoffice/phpspreadsheet": "^1.18",
-        "overtrue/easy-sms": "^2.0"
+        "overtrue/easy-sms": "^2.0",
+        "yiovo/tp6-captcha": "^1.1"
     },
     "require-dev": {
         "symfony/var-dumper": "^4.2",

+ 94 - 1
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "0f9f50572ec0a76614af87a4b1acdb01",
+    "content-hash": "af14364ae5e5a0568b74895761221a25",
     "packages": [
         {
             "name": "aliyuncs/oss-sdk-php",
@@ -2337,6 +2337,99 @@
                 "wiki": "http://doc.workerman.net/"
             },
             "time": "2020-08-24T03:49:23+00:00"
+        },
+        {
+            "name": "yiovo/tp6-cache",
+            "version": "v1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/yiovo/tp6-cache.git",
+                "reference": "31e0b5aaa1315ef85d7e68ed189bdb68406becfe"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/yiovo/tp6-cache/zipball/31e0b5aaa1315ef85d7e68ed189bdb68406becfe",
+                "reference": "31e0b5aaa1315ef85d7e68ed189bdb68406becfe",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1.0",
+                "topthink/framework": "^6.0.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "yiovo\\cache\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "yiovo",
+                    "email": "developer@yiovo.com"
+                }
+            ],
+            "description": "tp6-cache",
+            "homepage": "https://github.com/yiovo/tp6-captcha",
+            "support": {
+                "issues": "https://github.com/yiovo/tp6-cache/issues",
+                "source": "https://github.com/yiovo/tp6-cache/tree/v1.0.1"
+            },
+            "time": "2021-11-27T18:53:07+00:00"
+        },
+        {
+            "name": "yiovo/tp6-captcha",
+            "version": "v1.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/yiovo/tp6-captcha.git",
+                "reference": "ee3580516de48500cd02bcea01031eb6cb9f7d2d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/yiovo/tp6-captcha/zipball/ee3580516de48500cd02bcea01031eb6cb9f7d2d",
+                "reference": "ee3580516de48500cd02bcea01031eb6cb9f7d2d",
+                "shasum": ""
+            },
+            "require": {
+                "ext-gd": "*",
+                "ext-mbstring": "*",
+                "php": ">=7.1.0",
+                "topthink/framework": "^6.0.0",
+                "yiovo/tp6-cache": "^1.0"
+            },
+            "type": "library",
+            "extra": {
+                "think": {
+                    "config": {
+                        "captcha": "src/config.php"
+                    }
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "yiovo\\captcha\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "yiovo",
+                    "email": "developer@yiovo.com"
+                }
+            ],
+            "description": "tp6-captcha",
+            "homepage": "https://github.com/yiovo/tp6-captcha",
+            "support": {
+                "source": "https://github.com/yiovo/tp6-captcha/tree/v1.1.1"
+            },
+            "time": "2021-11-27T19:12:51+00:00"
         }
     ],
     "packages-dev": [

+ 2 - 6
config/captcha.php

@@ -30,10 +30,6 @@ return [
     'imageH' => 0,
     // 验证码图片宽度
     'imageW' => 0,
-
-    // 添加额外的验证码设置
-    // verify => [
-    //     'length'=>4,
-    //    ...
-    //],
+    // 验证码可重复验证的次数
+    'checkTimes' => 5,
 ];

+ 2 - 0
vendor/composer/autoload_psr4.php

@@ -6,6 +6,8 @@ $vendorDir = dirname(dirname(__FILE__));
 $baseDir = dirname($vendorDir);
 
 return array(
+    'yiovo\\captcha\\' => array($vendorDir . '/yiovo/tp6-captcha/src'),
+    'yiovo\\cache\\' => array($vendorDir . '/yiovo/tp6-cache/src'),
     'think\\worker\\' => array($vendorDir . '/topthink/think-worker/src'),
     'think\\trace\\' => array($vendorDir . '/topthink/think-trace/src'),
     'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'),

+ 13 - 0
vendor/composer/autoload_static.php

@@ -79,6 +79,11 @@ class ComposerStaticInitb17d9cf9df517c3dd2f492a1c933c315
     );
 
     public static $prefixLengthsPsr4 = array (
+        'y' => 
+        array (
+            'yiovo\\captcha\\' => 14,
+            'yiovo\\cache\\' => 12,
+        ),
         't' => 
         array (
             'think\\worker\\' => 13,
@@ -155,6 +160,14 @@ class ComposerStaticInitb17d9cf9df517c3dd2f492a1c933c315
     );
 
     public static $prefixDirsPsr4 = array (
+        'yiovo\\captcha\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/yiovo/tp6-captcha/src',
+        ),
+        'yiovo\\cache\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/yiovo/tp6-cache/src',
+        ),
         'think\\worker\\' => 
         array (
             0 => __DIR__ . '/..' . '/topthink/think-worker/src',

+ 99 - 0
vendor/composer/installed.json

@@ -2762,6 +2762,105 @@
                 "wiki": "http://doc.workerman.net/"
             },
             "install-path": "../workerman/workerman"
+        },
+        {
+            "name": "yiovo/tp6-cache",
+            "version": "v1.0.1",
+            "version_normalized": "1.0.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/yiovo/tp6-cache.git",
+                "reference": "31e0b5aaa1315ef85d7e68ed189bdb68406becfe"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/yiovo/tp6-cache/zipball/31e0b5aaa1315ef85d7e68ed189bdb68406becfe",
+                "reference": "31e0b5aaa1315ef85d7e68ed189bdb68406becfe",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1.0",
+                "topthink/framework": "^6.0.0"
+            },
+            "time": "2021-11-27T18:53:07+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "yiovo\\cache\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "yiovo",
+                    "email": "developer@yiovo.com"
+                }
+            ],
+            "description": "tp6-cache",
+            "homepage": "https://github.com/yiovo/tp6-captcha",
+            "support": {
+                "issues": "https://github.com/yiovo/tp6-cache/issues",
+                "source": "https://github.com/yiovo/tp6-cache/tree/v1.0.1"
+            },
+            "install-path": "../yiovo/tp6-cache"
+        },
+        {
+            "name": "yiovo/tp6-captcha",
+            "version": "v1.1.1",
+            "version_normalized": "1.1.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/yiovo/tp6-captcha.git",
+                "reference": "ee3580516de48500cd02bcea01031eb6cb9f7d2d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/yiovo/tp6-captcha/zipball/ee3580516de48500cd02bcea01031eb6cb9f7d2d",
+                "reference": "ee3580516de48500cd02bcea01031eb6cb9f7d2d",
+                "shasum": ""
+            },
+            "require": {
+                "ext-gd": "*",
+                "ext-mbstring": "*",
+                "php": ">=7.1.0",
+                "topthink/framework": "^6.0.0",
+                "yiovo/tp6-cache": "^1.0"
+            },
+            "time": "2021-11-27T19:12:51+00:00",
+            "type": "library",
+            "extra": {
+                "think": {
+                    "config": {
+                        "captcha": "src/config.php"
+                    }
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "yiovo\\captcha\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "yiovo",
+                    "email": "developer@yiovo.com"
+                }
+            ],
+            "description": "tp6-captcha",
+            "homepage": "https://github.com/yiovo/tp6-captcha",
+            "support": {
+                "source": "https://github.com/yiovo/tp6-captcha/tree/v1.1.1"
+            },
+            "install-path": "../yiovo/tp6-captcha"
         }
     ],
     "dev": true,

+ 20 - 2
vendor/composer/installed.php

@@ -5,7 +5,7 @@
         'type' => 'project',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
-        'reference' => '8c86675460affa759294bac5d9ca3530b972921c',
+        'reference' => '8c46a0101b71273889a673a61ce0071983d05974',
         'name' => 'topthink/think',
         'dev' => true,
     ),
@@ -463,7 +463,7 @@
             'type' => 'project',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),
-            'reference' => '8c86675460affa759294bac5d9ca3530b972921c',
+            'reference' => '8c46a0101b71273889a673a61ce0071983d05974',
             'dev_requirement' => false,
         ),
         'topthink/think-helper' => array(
@@ -529,5 +529,23 @@
             'reference' => 'b73ddc45b3c7299f330923a2bde23ca6e974fd96',
             'dev_requirement' => false,
         ),
+        'yiovo/tp6-cache' => array(
+            'pretty_version' => 'v1.0.1',
+            'version' => '1.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../yiovo/tp6-cache',
+            'aliases' => array(),
+            'reference' => '31e0b5aaa1315ef85d7e68ed189bdb68406becfe',
+            'dev_requirement' => false,
+        ),
+        'yiovo/tp6-captcha' => array(
+            'pretty_version' => 'v1.1.1',
+            'version' => '1.1.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../yiovo/tp6-captcha',
+            'aliases' => array(),
+            'reference' => 'ee3580516de48500cd02bcea01031eb6cb9f7d2d',
+            'dev_requirement' => false,
+        ),
     ),
 );

+ 1 - 1
vendor/services.php

@@ -1,5 +1,5 @@
 <?php 
-// This file is automatically generated at:2021-11-30 01:09:12
+// This file is automatically generated at:2021-11-30 01:09:54
 declare (strict_types = 1);
 return array (
   0 => 'think\\app\\Service',

+ 5 - 0
vendor/yiovo/tp6-cache/.gitignore

@@ -0,0 +1,5 @@
+/vendor
+/.idea
+composer.phar
+composer.lock
+.DS_Store

+ 191 - 0
vendor/yiovo/tp6-cache/LICENSE

@@ -0,0 +1,191 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate
+notice, with the fields enclosed by brackets "{}" replaced with your own
+identifying information. (Don't include the brackets!) The text should be
+enclosed in the appropriate comment syntax for the file format. We also
+recommend that a file or class name and description of purpose be included on
+the same "printed page" as the copyright notice for easier identification within
+third-party archives.
+
+   Copyright 2018 萤火科技
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 11 - 0
vendor/yiovo/tp6-cache/README.md

@@ -0,0 +1,11 @@
+## tp6-cache
+
+thinkphp6 缓存类 (二次开发版)
+
+#### 新增方法:
+
+`Cache::ttl(string $name)` 获取缓存剩余有效期(秒)
+
+`Cache::update(string $name, $newVal, bool $isMerge = true)` 更新缓存内容 (该方法区别于set方法,set方法不支持更新内容同时保留缓存剩余有效期)
+
+

+ 21 - 0
vendor/yiovo/tp6-cache/composer.json

@@ -0,0 +1,21 @@
+{
+  "name": "yiovo/tp6-cache",
+  "description": "tp6-cache",
+  "license": "Apache-2.0",
+  "authors": [
+    {
+      "name": "yiovo",
+      "email": "developer@yiovo.com"
+    }
+  ],
+  "require": {
+    "php": ">=7.1.0",
+    "topthink/framework": "^6.0.0"
+  },
+  "homepage": "https://github.com/yiovo/tp6-captcha",
+  "autoload": {
+    "psr-4": {
+      "yiovo\\cache\\": "src"
+    }
+  }
+}

+ 198 - 0
vendor/yiovo/tp6-cache/src/Cache.php

@@ -0,0 +1,198 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace yiovo\cache;
+
+use think\Manager;
+use think\cache\Driver;
+use think\cache\TagSet;
+use think\helper\Arr;
+use think\exception\InvalidArgumentException;
+use Psr\SimpleCache\CacheInterface;
+
+/**
+ * 缓存管理类
+ * @mixin Driver
+ * @mixin \yiovo\cache\cache\driver\File
+ */
+class Cache extends Manager implements CacheInterface
+{
+
+    protected $namespace = '\\yiovo\\cache\\cache\\driver\\';
+
+    /**
+     * 默认驱动
+     * @return string|null
+     */
+    public function getDefaultDriver()
+    {
+        return $this->getConfig('default');
+    }
+
+    /**
+     * 获取缓存配置
+     * @access public
+     * @param null|string $name 名称
+     * @param mixed $default 默认值
+     * @return mixed
+     */
+    public function getConfig(string $name = null, $default = null)
+    {
+        if (!is_null($name)) {
+            return $this->app->config->get('cache.' . $name, $default);
+        }
+
+        return $this->app->config->get('cache');
+    }
+
+    /**
+     * 获取驱动配置
+     * @param string $store
+     * @param string|null $name
+     * @param null $default
+     * @return array
+     */
+    public function getStoreConfig(string $store, string $name = null, $default = null)
+    {
+        if ($config = $this->getConfig("stores.{$store}")) {
+            return Arr::get($config, $name, $default);
+        }
+
+        throw new \InvalidArgumentException("Store [$store] not found.");
+    }
+
+    protected function resolveType(string $name)
+    {
+        return $this->getStoreConfig($name, 'type', 'file');
+    }
+
+    protected function resolveConfig(string $name)
+    {
+        return $this->getStoreConfig($name);
+    }
+
+    /**
+     * 连接或者切换缓存
+     * @access public
+     * @param string|null $name 连接配置名
+     * @return Driver
+     */
+    public function store(string $name = null)
+    {
+        return $this->driver($name);
+    }
+
+    /**
+     * 清空缓冲池
+     * @access public
+     * @return bool
+     */
+    public function clear(): bool
+    {
+        return $this->store()->clear();
+    }
+
+    /**
+     * 读取缓存
+     * @access public
+     * @param string $key 缓存变量名
+     * @param mixed $default 默认值
+     * @return mixed
+     */
+    public function get($key, $default = null)
+    {
+        return $this->store()->get($key, $default);
+    }
+
+    /**
+     * 写入缓存
+     * @access public
+     * @param string $key 缓存变量名
+     * @param mixed $value 存储数据
+     * @param int|\DateTime $ttl 有效时间 0为永久
+     * @return bool
+     */
+    public function set($key, $value, $ttl = null): bool
+    {
+        return $this->store()->set($key, $value, $ttl);
+    }
+
+    /**
+     * 删除缓存
+     * @access public
+     * @param string $key 缓存变量名
+     * @return bool
+     */
+    public function delete($key): bool
+    {
+        return $this->store()->delete($key);
+    }
+
+    /**
+     * 读取缓存
+     * @access public
+     * @param iterable $keys 缓存变量名
+     * @param mixed $default 默认值
+     * @return iterable
+     * @throws InvalidArgumentException
+     */
+    public function getMultiple($keys, $default = null): iterable
+    {
+        return $this->store()->getMultiple($keys, $default);
+    }
+
+    /**
+     * 写入缓存
+     * @access public
+     * @param iterable $values 缓存数据
+     * @param null|int|\DateInterval $ttl 有效时间 0为永久
+     * @return bool
+     */
+    public function setMultiple($values, $ttl = null): bool
+    {
+        return $this->store()->setMultiple($values, $ttl);
+    }
+
+    /**
+     * 删除缓存
+     * @access public
+     * @param iterable $keys 缓存变量名
+     * @return bool
+     * @throws InvalidArgumentException
+     */
+    public function deleteMultiple($keys): bool
+    {
+        return $this->store()->deleteMultiple($keys);
+    }
+
+    /**
+     * 判断缓存是否存在
+     * @access public
+     * @param string $key 缓存变量名
+     * @return bool
+     */
+    public function has($key): bool
+    {
+        return $this->store()->has($key);
+    }
+
+    /**
+     * 缓存标签
+     * @access public
+     * @param string|array $name 标签名
+     * @return TagSet
+     */
+    public function tag($name): TagSet
+    {
+        return $this->store()->tag($name);
+    }
+}

+ 357 - 0
vendor/yiovo/tp6-cache/src/cache/Driver.php

@@ -0,0 +1,357 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace yiovo\cache\cache;
+
+use Closure;
+use DateInterval;
+use DateTime;
+use DateTimeInterface;
+use Exception;
+use Psr\SimpleCache\CacheInterface;
+use think\Container;
+use think\contract\CacheHandlerInterface;
+use think\exception\InvalidArgumentException;
+use throwable;
+
+/**
+ * 缓存基础类
+ */
+abstract class Driver implements CacheInterface, CacheHandlerInterface
+{
+    /**
+     * 驱动句柄
+     * @var object
+     */
+    protected $handler = null;
+
+    /**
+     * 缓存读取次数
+     * @var integer
+     */
+    protected $readTimes = 0;
+
+    /**
+     * 缓存写入次数
+     * @var integer
+     */
+    protected $writeTimes = 0;
+
+    /**
+     * 缓存参数
+     * @var array
+     */
+    protected $options = [];
+
+    /**
+     * 缓存标签
+     * @var array
+     */
+    protected $tag = [];
+
+    /**
+     * 获取有效期
+     * @access protected
+     * @param integer|DateTimeInterface|DateInterval $expire 有效期
+     * @return int
+     */
+    protected function getExpireTime($expire): int
+    {
+        if ($expire instanceof DateTimeInterface) {
+            $expire = $expire->getTimestamp() - time();
+        } elseif ($expire instanceof DateInterval) {
+            $expire = DateTime::createFromFormat('U', (string) time())
+                ->add($expire)
+                ->format('U') - time();
+        }
+
+        return (int) $expire;
+    }
+
+    /**
+     * 获取实际的缓存标识
+     * @access public
+     * @param string $name 缓存名
+     * @return string
+     */
+    public function getCacheKey(string $name): string
+    {
+        return $this->options['prefix'] . $name;
+    }
+
+    /**
+     * 读取缓存并删除
+     * @access public
+     * @param string $name 缓存变量名
+     * @return mixed
+     */
+    public function pull(string $name)
+    {
+        $result = $this->get($name, false);
+
+        if ($result) {
+            $this->delete($name);
+            return $result;
+        }
+    }
+
+    /**
+     * 追加(数组)缓存
+     * @access public
+     * @param string $name  缓存变量名
+     * @param mixed  $value 存储数据
+     * @return void
+     */
+    public function push(string $name, $value): void
+    {
+        $item = $this->get($name, []);
+
+        if (!is_array($item)) {
+            throw new InvalidArgumentException('only array cache can be push');
+        }
+
+        $item[] = $value;
+
+        if (count($item) > 1000) {
+            array_shift($item);
+        }
+
+        $item = array_unique($item);
+
+        $this->set($name, $item);
+    }
+
+    /**
+     * 追加TagSet数据
+     * @access public
+     * @param string $name  缓存变量名
+     * @param mixed  $value 存储数据
+     * @return void
+     */
+    public function append(string $name, $value): void
+    {
+        $this->push($name, $value);
+    }
+
+    /**
+     * 如果不存在则写入缓存
+     * @access public
+     * @param string $name   缓存变量名
+     * @param mixed  $value  存储数据
+     * @param int    $expire 有效时间 0为永久
+     * @return mixed
+     */
+    public function remember(string $name, $value, $expire = null)
+    {
+        if ($this->has($name)) {
+            return $this->get($name);
+        }
+
+        $time = time();
+
+        while ($time + 5 > time() && $this->has($name . '_lock')) {
+            // 存在锁定则等待
+            usleep(200000);
+        }
+
+        try {
+            // 锁定
+            $this->set($name . '_lock', true);
+
+            if ($value instanceof Closure) {
+                // 获取缓存数据
+                $value = Container::getInstance()->invokeFunction($value);
+            }
+
+            // 缓存数据
+            $this->set($name, $value, $expire);
+
+            // 解锁
+            $this->delete($name . '_lock');
+        } catch (Exception | throwable $e) {
+            $this->delete($name . '_lock');
+            throw $e;
+        }
+
+        return $value;
+    }
+
+    /**
+     * 缓存标签
+     * @access public
+     * @param string|array $name 标签名
+     * @return TagSet
+     */
+    public function tag($name): TagSet
+    {
+        $name = (array) $name;
+        $key  = implode('-', $name);
+
+        if (!isset($this->tag[$key])) {
+            $this->tag[$key] = new TagSet($name, $this);
+        }
+
+        return $this->tag[$key];
+    }
+
+    /**
+     * 获取标签包含的缓存标识
+     * @access public
+     * @param string $tag 标签标识
+     * @return array
+     */
+    public function getTagItems(string $tag): array
+    {
+        $name = $this->getTagKey($tag);
+        return $this->get($name, []);
+    }
+
+    /**
+     * 获取实际标签名
+     * @access public
+     * @param string $tag 标签名
+     * @return string
+     */
+    public function getTagKey(string $tag): string
+    {
+        return $this->options['tag_prefix'] . md5($tag);
+    }
+
+    /**
+     * 序列化数据
+     * @access protected
+     * @param mixed $data 缓存数据
+     * @return string
+     */
+    protected function serialize($data): string
+    {
+        if (is_numeric($data)) {
+            return (string) $data;
+        }
+
+        $serialize = $this->options['serialize'][0] ?? "serialize";
+
+        return $serialize($data);
+    }
+
+    /**
+     * 反序列化数据
+     * @access protected
+     * @param string $data 缓存数据
+     * @return mixed
+     */
+    protected function unserialize(string $data)
+    {
+        if (is_numeric($data)) {
+            return $data;
+        }
+
+        $unserialize = $this->options['serialize'][1] ?? "unserialize";
+
+        return $unserialize($data);
+    }
+
+    /**
+     * 返回句柄对象,可执行其它高级方法
+     *
+     * @access public
+     * @return object
+     */
+    public function handler()
+    {
+        return $this->handler;
+    }
+
+    /**
+     * 返回缓存读取次数
+     * @access public
+     * @return int
+     */
+    public function getReadTimes(): int
+    {
+        return $this->readTimes;
+    }
+
+    /**
+     * 返回缓存写入次数
+     * @access public
+     * @return int
+     */
+    public function getWriteTimes(): int
+    {
+        return $this->writeTimes;
+    }
+
+    /**
+     * 读取缓存
+     * @access public
+     * @param iterable $keys    缓存变量名
+     * @param mixed    $default 默认值
+     * @return iterable
+     * @throws InvalidArgumentException
+     */
+    public function getMultiple($keys, $default = null): iterable
+    {
+        $result = [];
+
+        foreach ($keys as $key) {
+            $result[$key] = $this->get($key, $default);
+        }
+
+        return $result;
+    }
+
+    /**
+     * 写入缓存
+     * @access public
+     * @param iterable               $values 缓存数据
+     * @param null|int|\DateInterval $ttl    有效时间 0为永久
+     * @return bool
+     */
+    public function setMultiple($values, $ttl = null): bool
+    {
+        foreach ($values as $key => $val) {
+            $result = $this->set($key, $val, $ttl);
+
+            if (false === $result) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * 删除缓存
+     * @access public
+     * @param iterable $keys 缓存变量名
+     * @return bool
+     * @throws InvalidArgumentException
+     */
+    public function deleteMultiple($keys): bool
+    {
+        foreach ($keys as $key) {
+            $result = $this->delete($key);
+
+            if (false === $result) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public function __call($method, $args)
+    {
+        return call_user_func_array([$this->handler, $method], $args);
+    }
+}

+ 132 - 0
vendor/yiovo/tp6-cache/src/cache/TagSet.php

@@ -0,0 +1,132 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace yiovo\cache\cache;
+
+/**
+ * 标签集合
+ */
+class TagSet
+{
+    /**
+     * 标签的缓存Key
+     * @var array
+     */
+    protected $tag;
+
+    /**
+     * 缓存句柄
+     * @var Driver
+     */
+    protected $handler;
+
+    /**
+     * 架构函数
+     * @access public
+     * @param array  $tag   缓存标签
+     * @param Driver $cache 缓存对象
+     */
+    public function __construct(array $tag, Driver $cache)
+    {
+        $this->tag     = $tag;
+        $this->handler = $cache;
+    }
+
+    /**
+     * 写入缓存
+     * @access public
+     * @param string            $name   缓存变量名
+     * @param mixed             $value  存储数据
+     * @param integer|\DateTime $expire 有效时间(秒)
+     * @return bool
+     */
+    public function set(string $name, $value, $expire = null): bool
+    {
+        $this->handler->set($name, $value, $expire);
+
+        $this->append($name);
+
+        return true;
+    }
+
+    /**
+     * 追加缓存标识到标签
+     * @access public
+     * @param string $name 缓存变量名
+     * @return void
+     */
+    public function append(string $name): void
+    {
+        $name = $this->handler->getCacheKey($name);
+
+        foreach ($this->tag as $tag) {
+            $key = $this->handler->getTagKey($tag);
+            $this->handler->append($key, $name);
+        }
+    }
+
+    /**
+     * 写入缓存
+     * @access public
+     * @param iterable               $values 缓存数据
+     * @param null|int|\DateInterval $ttl    有效时间 0为永久
+     * @return bool
+     */
+    public function setMultiple($values, $ttl = null): bool
+    {
+        foreach ($values as $key => $val) {
+            $result = $this->set($key, $val, $ttl);
+
+            if (false === $result) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * 如果不存在则写入缓存
+     * @access public
+     * @param string $name   缓存变量名
+     * @param mixed  $value  存储数据
+     * @param int    $expire 有效时间 0为永久
+     * @return mixed
+     */
+    public function remember(string $name, $value, $expire = null)
+    {
+        $result = $this->handler->remember($name, $value, $expire);
+
+        $this->append($name);
+
+        return $result;
+    }
+
+    /**
+     * 清除缓存
+     * @access public
+     * @return bool
+     */
+    public function clear(): bool
+    {
+        // 指定标签清除
+        foreach ($this->tag as $tag) {
+            $names = $this->handler->getTagItems($tag);
+            $this->handler->clearTag($names);
+
+            $key = $this->handler->getTagKey($tag);
+            $this->handler->delete($key);
+        }
+
+        return true;
+    }
+}

+ 342 - 0
vendor/yiovo/tp6-cache/src/cache/driver/File.php

@@ -0,0 +1,342 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace yiovo\cache\cache\driver;
+
+use FilesystemIterator;
+use think\App;
+use yiovo\cache\cache\Driver;
+
+/**
+ * 文件缓存类
+ */
+class File extends Driver
+{
+    /**
+     * 配置参数
+     * @var array
+     */
+    protected $options = [
+        'expire' => 0,
+        'cache_subdir' => true,
+        'prefix' => '',
+        'path' => '',
+        'hash_type' => 'md5',
+        'data_compress' => false,
+        'tag_prefix' => 'tag:',
+        'serialize' => [],
+    ];
+
+    /**
+     * 架构函数
+     * @param App $app
+     * @param array $options 参数
+     */
+    public function __construct(App $app, array $options = [])
+    {
+        if (!empty($options)) {
+            $this->options = array_merge($this->options, $options);
+        }
+
+        if (empty($this->options['path'])) {
+            $this->options['path'] = $app->getRuntimePath() . 'cache';
+        }
+
+        if (substr($this->options['path'], -1) != DIRECTORY_SEPARATOR) {
+            $this->options['path'] .= DIRECTORY_SEPARATOR;
+        }
+    }
+
+    /**
+     * 取得变量的存储文件名
+     * @access public
+     * @param string $name 缓存变量名
+     * @return string
+     */
+    public function getCacheKey(string $name): string
+    {
+        $name = hash($this->options['hash_type'], $name);
+
+        if ($this->options['cache_subdir']) {
+            // 使用子目录
+            $name = substr($name, 0, 2) . DIRECTORY_SEPARATOR . substr($name, 2);
+        }
+
+        if ($this->options['prefix']) {
+            $name = $this->options['prefix'] . DIRECTORY_SEPARATOR . $name;
+        }
+
+        return $this->options['path'] . $name . '.php';
+    }
+
+    /**
+     * 获取缓存数据
+     * @param string $name 缓存标识名
+     * @return array|null
+     */
+    protected function getRaw(string $name)
+    {
+        $filename = $this->getCacheKey($name);
+
+        if (!is_file($filename)) {
+            return;
+        }
+
+        $content = @file_get_contents($filename);
+
+        if (false !== $content) {
+            $expire = (int)substr($content, 8, 12);
+            if (0 != $expire && time() - $expire > filemtime($filename)) {
+                //缓存过期删除缓存文件
+                $this->unlink($filename);
+                return;
+            }
+
+            $content = substr($content, 32);
+
+            if ($this->options['data_compress'] && function_exists('gzcompress')) {
+                //启用数据压缩
+                $content = gzuncompress($content);
+            }
+
+            return is_string($content) ? [
+                'content' => $content,
+                'expire' => $expire,
+                'filemtime' => filemtime($filename)
+            ] : null;
+        }
+    }
+
+    /**
+     * 判断缓存是否存在
+     * @access public
+     * @param string $name 缓存变量名
+     * @return bool
+     */
+    public function has($name): bool
+    {
+        return $this->getRaw($name) !== null;
+    }
+
+    /**
+     * 读取缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @param mixed $default 默认值
+     * @return mixed
+     */
+    public function get($name, $default = null)
+    {
+        $this->readTimes++;
+
+        $raw = $this->getRaw($name);
+
+        return is_null($raw) ? $default : $this->unserialize($raw['content']);
+    }
+
+    /**
+     * 写入缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @param mixed $value 存储数据
+     * @param int|\DateTime $expire 有效时间 0为永久
+     * @return bool
+     */
+    public function set($name, $value, $expire = null): bool
+    {
+        $this->writeTimes++;
+
+        if (is_null($expire)) {
+            $expire = $this->options['expire'];
+        }
+
+        $expire = $this->getExpireTime($expire);
+        $filename = $this->getCacheKey($name);
+
+        $dir = dirname($filename);
+
+        if (!is_dir($dir)) {
+            try {
+                mkdir($dir, 0755, true);
+            } catch (\Exception $e) {
+                // 创建失败
+            }
+        }
+
+        $data = $this->serialize($value);
+
+        if ($this->options['data_compress'] && function_exists('gzcompress')) {
+            //数据压缩
+            $data = gzcompress($data, 3);
+        }
+
+        $data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
+        $result = file_put_contents($filename, $data);
+
+        if ($result) {
+            clearstatcache();
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * 自增缓存(针对数值缓存)
+     * @access public
+     * @param string $name 缓存变量名
+     * @param int $step 步长
+     * @return false|int
+     */
+    public function inc(string $name, int $step = 1)
+    {
+        if ($raw = $this->getRaw($name)) {
+            $value = $this->unserialize($raw['content']) + $step;
+            $expire = $raw['expire'];
+        } else {
+            $value = $step;
+            $expire = 0;
+        }
+
+        return $this->set($name, $value, $expire) ? $value : false;
+    }
+
+    /**
+     * 自减缓存(针对数值缓存)
+     * @access public
+     * @param string $name 缓存变量名
+     * @param int $step 步长
+     * @return false|int
+     */
+    public function dec(string $name, int $step = 1)
+    {
+        return $this->inc($name, -$step);
+    }
+
+    /**
+     * 删除缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @return bool
+     */
+    public function delete($name): bool
+    {
+        $this->writeTimes++;
+
+        return $this->unlink($this->getCacheKey($name));
+    }
+
+    /**
+     * 清除缓存
+     * @access public
+     * @return bool
+     */
+    public function clear(): bool
+    {
+        $this->writeTimes++;
+
+        $dirname = $this->options['path'] . $this->options['prefix'];
+
+        $this->rmdir($dirname);
+
+        return true;
+    }
+
+    /**
+     * 删除缓存标签
+     * @access public
+     * @param array $keys 缓存标识列表
+     * @return void
+     */
+    public function clearTag(array $keys): void
+    {
+        foreach ($keys as $key) {
+            $this->unlink($key);
+        }
+    }
+
+    /**
+     * 判断文件是否存在后,删除
+     * @access private
+     * @param string $path
+     * @return bool
+     */
+    private function unlink(string $path): bool
+    {
+        try {
+            return is_file($path) && unlink($path);
+        } catch (\Exception $e) {
+            return false;
+        }
+    }
+
+    /**
+     * 删除文件夹
+     * @param $dirname
+     * @return bool
+     */
+    private function rmdir($dirname)
+    {
+        if (!is_dir($dirname)) {
+            return false;
+        }
+
+        $items = new FilesystemIterator($dirname);
+
+        foreach ($items as $item) {
+            if ($item->isDir() && !$item->isLink()) {
+                $this->rmdir($item->getPathname());
+            } else {
+                $this->unlink($item->getPathname());
+            }
+        }
+
+        @rmdir($dirname);
+
+        return true;
+    }
+
+    /**
+     * 获取缓存剩余有效期(秒)
+     * @param string $name 缓存标识名
+     * @return int
+     */
+    public function ttl(string $name): int
+    {
+        $raw = $this->getRaw($name);
+        if (empty($raw) || empty($raw['expire'])) {
+            return 0;
+        }
+        return $raw['filemtime'] + $raw['expire'] - time();
+    }
+
+    /**
+     * 更新缓存内容
+     * 该方法区别于set方法,set方法不支持更新内容同时保留缓存剩余有效期
+     * @param string $name 缓存标识名
+     * @param mixed $newVal 新的内容
+     * @param bool $isMerge 是否与更新前的数据合并(仅数组类型有效)
+     * @return bool
+     */
+    public function update(string $name, $newVal, bool $isMerge = true): bool
+    {
+        $raw = $this->getRaw($name);
+        if (empty($raw)) {
+            throw new \InvalidArgumentException('cache name not found');
+        }
+        $value = $this->unserialize($raw['content']);
+        if (is_array($value) && is_array($newVal) && $isMerge) {
+            $newVal = array_merge($value, $newVal);
+        }
+        return $this->set($name, $newVal, $this->ttl($name));
+    }
+}

+ 209 - 0
vendor/yiovo/tp6-cache/src/cache/driver/Memcache.php

@@ -0,0 +1,209 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace yiovo\cache\cache\driver;
+
+use yiovo\cache\cache\Driver;
+
+/**
+ * Memcache缓存类
+ */
+class Memcache extends Driver
+{
+    /**
+     * 配置参数
+     * @var array
+     */
+    protected $options = [
+        'host' => '127.0.0.1',
+        'port' => 11211,
+        'expire' => 0,
+        'timeout' => 0, // 超时时间(单位:毫秒)
+        'persistent' => true,
+        'prefix' => '',
+        'tag_prefix' => 'tag:',
+        'serialize' => [],
+    ];
+
+    /**
+     * 架构函数
+     * @access public
+     * @param array $options 缓存参数
+     * @throws \BadFunctionCallException
+     */
+    public function __construct(array $options = [])
+    {
+        if (!extension_loaded('memcache')) {
+            throw new \BadFunctionCallException('not support: memcache');
+        }
+
+        if (!empty($options)) {
+            $this->options = array_merge($this->options, $options);
+        }
+
+        $this->handler = new \Memcache;
+
+        // 支持集群
+        $hosts = (array)$this->options['host'];
+        $ports = (array)$this->options['port'];
+
+        if (empty($ports[0])) {
+            $ports[0] = 11211;
+        }
+
+        // 建立连接
+        foreach ($hosts as $i => $host) {
+            $port = $ports[$i] ?? $ports[0];
+            $this->options['timeout'] > 0 ?
+                $this->handler->addServer($host, (int)$port, $this->options['persistent'], 1, (int)$this->options['timeout']) :
+                $this->handler->addServer($host, (int)$port, $this->options['persistent'], 1);
+        }
+    }
+
+    /**
+     * 判断缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @return bool
+     */
+    public function has($name): bool
+    {
+        $key = $this->getCacheKey($name);
+
+        return false !== $this->handler->get($key);
+    }
+
+    /**
+     * 读取缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @param mixed $default 默认值
+     * @return mixed
+     */
+    public function get($name, $default = null)
+    {
+        $this->readTimes++;
+
+        $result = $this->handler->get($this->getCacheKey($name));
+
+        return false !== $result ? $this->unserialize($result) : $default;
+    }
+
+    /**
+     * 写入缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @param mixed $value 存储数据
+     * @param int|\DateTime $expire 有效时间(秒)
+     * @return bool
+     */
+    public function set($name, $value, $expire = null): bool
+    {
+        $this->writeTimes++;
+
+        if (is_null($expire)) {
+            $expire = $this->options['expire'];
+        }
+
+        $key = $this->getCacheKey($name);
+        $expire = $this->getExpireTime($expire);
+        $value = $this->serialize($value);
+
+        if ($this->handler->set($key, $value, 0, $expire)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * 自增缓存(针对数值缓存)
+     * @access public
+     * @param string $name 缓存变量名
+     * @param int $step 步长
+     * @return false|int
+     */
+    public function inc(string $name, int $step = 1)
+    {
+        $this->writeTimes++;
+
+        $key = $this->getCacheKey($name);
+
+        if ($this->handler->get($key)) {
+            return $this->handler->increment($key, $step);
+        }
+
+        return $this->handler->set($key, $step);
+    }
+
+    /**
+     * 自减缓存(针对数值缓存)
+     * @access public
+     * @param string $name 缓存变量名
+     * @param int $step 步长
+     * @return false|int
+     */
+    public function dec(string $name, int $step = 1)
+    {
+        $this->writeTimes++;
+
+        $key = $this->getCacheKey($name);
+        $value = $this->handler->get($key) - $step;
+        $res = $this->handler->set($key, $value);
+
+        return !$res ? false : $value;
+    }
+
+    /**
+     * 删除缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @param bool|false $ttl
+     * @return bool
+     */
+    public function delete($name, $ttl = false): bool
+    {
+        $this->writeTimes++;
+
+        $key = $this->getCacheKey($name);
+
+        return false === $ttl ?
+            $this->handler->delete($key) :
+            $this->handler->delete($key, $ttl);
+    }
+
+    /**
+     * 清除缓存
+     * @access public
+     * @return bool
+     */
+    public function clear(): bool
+    {
+        $this->writeTimes++;
+
+        return $this->handler->flush();
+    }
+
+    /**
+     * 删除缓存标签
+     * @access public
+     * @param array $keys 缓存标识列表
+     * @return void
+     */
+    public function clearTag(array $keys): void
+    {
+        foreach ($keys as $key) {
+            $this->handler->delete($key);
+        }
+    }
+
+}

+ 221 - 0
vendor/yiovo/tp6-cache/src/cache/driver/Memcached.php

@@ -0,0 +1,221 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace yiovo\cache\cache\driver;
+
+use yiovo\cache\cache\Driver;
+
+/**
+ * Memcached缓存类
+ */
+class Memcached extends Driver
+{
+    /**
+     * 配置参数
+     * @var array
+     */
+    protected $options = [
+        'host'       => '127.0.0.1',
+        'port'       => 11211,
+        'expire'     => 0,
+        'timeout'    => 0, // 超时时间(单位:毫秒)
+        'prefix'     => '',
+        'username'   => '', //账号
+        'password'   => '', //密码
+        'option'     => [],
+        'tag_prefix' => 'tag:',
+        'serialize'  => [],
+    ];
+
+    /**
+     * 架构函数
+     * @access public
+     * @param array $options 缓存参数
+     */
+    public function __construct(array $options = [])
+    {
+        if (!extension_loaded('memcached')) {
+            throw new \BadFunctionCallException('not support: memcached');
+        }
+
+        if (!empty($options)) {
+            $this->options = array_merge($this->options, $options);
+        }
+
+        $this->handler = new \Memcached;
+
+        if (!empty($this->options['option'])) {
+            $this->handler->setOptions($this->options['option']);
+        }
+
+        // 设置连接超时时间(单位:毫秒)
+        if ($this->options['timeout'] > 0) {
+            $this->handler->setOption(\Memcached::OPT_CONNECT_TIMEOUT, $this->options['timeout']);
+        }
+
+        // 支持集群
+        $hosts = (array) $this->options['host'];
+        $ports = (array) $this->options['port'];
+        if (empty($ports[0])) {
+            $ports[0] = 11211;
+        }
+
+        // 建立连接
+        $servers = [];
+        foreach ($hosts as $i => $host) {
+            $servers[] = [$host, $ports[$i] ?? $ports[0], 1];
+        }
+
+        $this->handler->addServers($servers);
+
+        if ('' != $this->options['username']) {
+            $this->handler->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);
+            $this->handler->setSaslAuthData($this->options['username'], $this->options['password']);
+        }
+    }
+
+    /**
+     * 判断缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @return bool
+     */
+    public function has($name): bool
+    {
+        $key = $this->getCacheKey($name);
+
+        return $this->handler->get($key) ? true : false;
+    }
+
+    /**
+     * 读取缓存
+     * @access public
+     * @param string $name    缓存变量名
+     * @param mixed  $default 默认值
+     * @return mixed
+     */
+    public function get($name, $default = null)
+    {
+        $this->readTimes++;
+
+        $result = $this->handler->get($this->getCacheKey($name));
+
+        return false !== $result ? $this->unserialize($result) : $default;
+    }
+
+    /**
+     * 写入缓存
+     * @access public
+     * @param string            $name   缓存变量名
+     * @param mixed             $value  存储数据
+     * @param integer|\DateTime $expire 有效时间(秒)
+     * @return bool
+     */
+    public function set($name, $value, $expire = null): bool
+    {
+        $this->writeTimes++;
+
+        if (is_null($expire)) {
+            $expire = $this->options['expire'];
+        }
+
+        $key    = $this->getCacheKey($name);
+        $expire = $this->getExpireTime($expire);
+        $value  = $this->serialize($value);
+
+        if ($this->handler->set($key, $value, $expire)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * 自增缓存(针对数值缓存)
+     * @access public
+     * @param string $name 缓存变量名
+     * @param int    $step 步长
+     * @return false|int
+     */
+    public function inc(string $name, int $step = 1)
+    {
+        $this->writeTimes++;
+
+        $key = $this->getCacheKey($name);
+
+        if ($this->handler->get($key)) {
+            return $this->handler->increment($key, $step);
+        }
+
+        return $this->handler->set($key, $step);
+    }
+
+    /**
+     * 自减缓存(针对数值缓存)
+     * @access public
+     * @param string $name 缓存变量名
+     * @param int    $step 步长
+     * @return false|int
+     */
+    public function dec(string $name, int $step = 1)
+    {
+        $this->writeTimes++;
+
+        $key   = $this->getCacheKey($name);
+        $value = $this->handler->get($key) - $step;
+        $res   = $this->handler->set($key, $value);
+
+        return !$res ? false : $value;
+    }
+
+    /**
+     * 删除缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @param bool|false $ttl
+     * @return bool
+     */
+    public function delete($name, $ttl = false): bool
+    {
+        $this->writeTimes++;
+
+        $key = $this->getCacheKey($name);
+
+        return false === $ttl ?
+        $this->handler->delete($key) :
+        $this->handler->delete($key, $ttl);
+    }
+
+    /**
+     * 清除缓存
+     * @access public
+     * @return bool
+     */
+    public function clear(): bool
+    {
+        $this->writeTimes++;
+
+        return $this->handler->flush();
+    }
+
+    /**
+     * 删除缓存标签
+     * @access public
+     * @param array $keys 缓存标识列表
+     * @return void
+     */
+    public function clearTag(array $keys): void
+    {
+        $this->handler->deleteMulti($keys);
+    }
+
+}

+ 277 - 0
vendor/yiovo/tp6-cache/src/cache/driver/Redis.php

@@ -0,0 +1,277 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace yiovo\cache\cache\driver;
+
+use yiovo\cache\cache\Driver;
+
+/**
+ * Redis缓存驱动,适合单机部署、有前端代理实现高可用的场景,性能最好
+ * 有需要在业务层实现读写分离、或者使用RedisCluster的需求,请使用Redisd驱动
+ *
+ * 要求安装phpredis扩展:https://github.com/nicolasff/phpredis
+ * @author    尘缘 <130775@qq.com>
+ */
+class Redis extends Driver
+{
+    /** @var \Predis\Client|\Redis */
+    protected $handler;
+
+    /**
+     * 配置参数
+     * @var array
+     */
+    protected $options = [
+        'host' => '127.0.0.1',
+        'port' => 6379,
+        'password' => '',
+        'select' => 0,
+        'timeout' => 0,
+        'expire' => 0,
+        'persistent' => false,
+        'prefix' => '',
+        'tag_prefix' => 'tag:',
+        'serialize' => [],
+    ];
+
+    /**
+     * 架构函数
+     * @access public
+     * @param array $options 缓存参数
+     */
+    public function __construct(array $options = [])
+    {
+        if (!empty($options)) {
+            $this->options = array_merge($this->options, $options);
+        }
+
+        if (extension_loaded('redis')) {
+            $this->handler = new \Redis;
+
+            if ($this->options['persistent']) {
+                $this->handler->pconnect($this->options['host'], (int)$this->options['port'], (int)$this->options['timeout'], 'persistent_id_' . $this->options['select']);
+            } else {
+                $this->handler->connect($this->options['host'], (int)$this->options['port'], (int)$this->options['timeout']);
+            }
+
+            if ('' != $this->options['password']) {
+                $this->handler->auth($this->options['password']);
+            }
+        } elseif (class_exists('\Predis\Client')) {
+            $params = [];
+            foreach ($this->options as $key => $val) {
+                if (in_array($key, ['aggregate', 'cluster', 'connections', 'exceptions', 'prefix', 'profile', 'replication', 'parameters'])) {
+                    $params[$key] = $val;
+                    unset($this->options[$key]);
+                }
+            }
+
+            if ('' == $this->options['password']) {
+                unset($this->options['password']);
+            }
+
+            $this->handler = new \Predis\Client($this->options, $params);
+
+            $this->options['prefix'] = '';
+        } else {
+            throw new \BadFunctionCallException('not support: redis');
+        }
+
+        if (0 != $this->options['select']) {
+            $this->handler->select((int)$this->options['select']);
+        }
+    }
+
+    /**
+     * 判断缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @return bool
+     */
+    public function has($name): bool
+    {
+        return $this->handler->exists($this->getCacheKey($name)) ? true : false;
+    }
+
+    /**
+     * 读取缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @param mixed $default 默认值
+     * @return mixed
+     */
+    public function get($name, $default = null)
+    {
+        $this->readTimes++;
+        $key = $this->getCacheKey($name);
+        $value = $this->handler->get($key);
+
+        if (false === $value || is_null($value)) {
+            return $default;
+        }
+
+        return $this->unserialize($value);
+    }
+
+    /**
+     * 写入缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @param mixed $value 存储数据
+     * @param integer|\DateTime $expire 有效时间(秒)
+     * @return bool
+     */
+    public function set($name, $value, $expire = null): bool
+    {
+        $this->writeTimes++;
+
+        if (is_null($expire)) {
+            $expire = $this->options['expire'];
+        }
+
+        $key = $this->getCacheKey($name);
+        $expire = $this->getExpireTime($expire);
+        $value = $this->serialize($value);
+
+        if ($expire) {
+            $this->handler->setex($key, $expire, $value);
+        } else {
+            $this->handler->set($key, $value);
+        }
+
+        return true;
+    }
+
+    /**
+     * 自增缓存(针对数值缓存)
+     * @access public
+     * @param string $name 缓存变量名
+     * @param int $step 步长
+     * @return false|int
+     */
+    public function inc(string $name, int $step = 1)
+    {
+        $this->writeTimes++;
+        $key = $this->getCacheKey($name);
+
+        return $this->handler->incrby($key, $step);
+    }
+
+    /**
+     * 自减缓存(针对数值缓存)
+     * @access public
+     * @param string $name 缓存变量名
+     * @param int $step 步长
+     * @return false|int
+     */
+    public function dec(string $name, int $step = 1)
+    {
+        $this->writeTimes++;
+        $key = $this->getCacheKey($name);
+
+        return $this->handler->decrby($key, $step);
+    }
+
+    /**
+     * 删除缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @return bool
+     */
+    public function delete($name): bool
+    {
+        $this->writeTimes++;
+
+        $key = $this->getCacheKey($name);
+        $result = $this->handler->del($key);
+        return $result > 0;
+    }
+
+    /**
+     * 清除缓存
+     * @access public
+     * @return bool
+     */
+    public function clear(): bool
+    {
+        $this->writeTimes++;
+        $this->handler->flushDB();
+        return true;
+    }
+
+    /**
+     * 删除缓存标签
+     * @access public
+     * @param array $keys 缓存标识列表
+     * @return void
+     */
+    public function clearTag(array $keys): void
+    {
+        // 指定标签清除
+        $this->handler->del($keys);
+    }
+
+    /**
+     * 追加TagSet数据
+     * @access public
+     * @param string $name 缓存标识
+     * @param mixed $value 数据
+     * @return void
+     */
+    public function append(string $name, $value): void
+    {
+        $key = $this->getCacheKey($name);
+        $this->handler->sAdd($key, $value);
+    }
+
+    /**
+     * 获取标签包含的缓存标识
+     * @access public
+     * @param string $tag 缓存标签
+     * @return array
+     */
+    public function getTagItems(string $tag): array
+    {
+        $name = $this->getTagKey($tag);
+        $key = $this->getCacheKey($name);
+        return $this->handler->sMembers($key);
+    }
+
+    /**
+     * 获取缓存剩余有效期(秒)
+     * @param string $name 缓存标识名
+     * @return int
+     */
+    public function ttl(string $name): int
+    {
+        $key = $this->getCacheKey($name);
+        return $this->handler->ttl($key);
+    }
+
+    /**
+     * 更新缓存内容
+     * 该方法区别于set方法,set方法不支持更新内容同时保留缓存剩余有效期
+     * @param string $name 缓存标识
+     * @param mixed $newVal 新的内容
+     * @param bool $isMerge 是否与更新前的数据合并(仅数组类型有效)
+     * @return true
+     */
+    public function update(string $name, $newVal, bool $isMerge = true): bool
+    {
+        $value = $this->get($name);
+        if (is_array($value) && is_array($newVal) && $isMerge) {
+            $newVal = array_merge($value, $newVal);
+        }
+        $this->set($name, $newVal, $this->ttl($name));
+        return true;
+    }
+}

+ 175 - 0
vendor/yiovo/tp6-cache/src/cache/driver/Wincache.php

@@ -0,0 +1,175 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace yiovo\cache\cache\driver;
+
+use yiovo\cache\cache\Driver;
+
+/**
+ * Wincache缓存驱动
+ */
+class Wincache extends Driver
+{
+    /**
+     * 配置参数
+     * @var array
+     */
+    protected $options = [
+        'prefix'     => '',
+        'expire'     => 0,
+        'tag_prefix' => 'tag:',
+        'serialize'  => [],
+    ];
+
+    /**
+     * 架构函数
+     * @access public
+     * @param array $options 缓存参数
+     * @throws \BadFunctionCallException
+     */
+    public function __construct(array $options = [])
+    {
+        if (!function_exists('wincache_ucache_info')) {
+            throw new \BadFunctionCallException('not support: WinCache');
+        }
+
+        if (!empty($options)) {
+            $this->options = array_merge($this->options, $options);
+        }
+    }
+
+    /**
+     * 判断缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @return bool
+     */
+    public function has($name): bool
+    {
+        $this->readTimes++;
+
+        $key = $this->getCacheKey($name);
+
+        return wincache_ucache_exists($key);
+    }
+
+    /**
+     * 读取缓存
+     * @access public
+     * @param string $name    缓存变量名
+     * @param mixed  $default 默认值
+     * @return mixed
+     */
+    public function get($name, $default = null)
+    {
+        $this->readTimes++;
+
+        $key = $this->getCacheKey($name);
+
+        return wincache_ucache_exists($key) ? $this->unserialize(wincache_ucache_get($key)) : $default;
+    }
+
+    /**
+     * 写入缓存
+     * @access public
+     * @param string            $name   缓存变量名
+     * @param mixed             $value  存储数据
+     * @param integer|\DateTime $expire 有效时间(秒)
+     * @return bool
+     */
+    public function set($name, $value, $expire = null): bool
+    {
+        $this->writeTimes++;
+
+        if (is_null($expire)) {
+            $expire = $this->options['expire'];
+        }
+
+        $key    = $this->getCacheKey($name);
+        $expire = $this->getExpireTime($expire);
+        $value  = $this->serialize($value);
+
+        if (wincache_ucache_set($key, $value, $expire)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * 自增缓存(针对数值缓存)
+     * @access public
+     * @param string $name 缓存变量名
+     * @param int    $step 步长
+     * @return false|int
+     */
+    public function inc(string $name, int $step = 1)
+    {
+        $this->writeTimes++;
+
+        $key = $this->getCacheKey($name);
+
+        return wincache_ucache_inc($key, $step);
+    }
+
+    /**
+     * 自减缓存(针对数值缓存)
+     * @access public
+     * @param string $name 缓存变量名
+     * @param int    $step 步长
+     * @return false|int
+     */
+    public function dec(string $name, int $step = 1)
+    {
+        $this->writeTimes++;
+
+        $key = $this->getCacheKey($name);
+
+        return wincache_ucache_dec($key, $step);
+    }
+
+    /**
+     * 删除缓存
+     * @access public
+     * @param string $name 缓存变量名
+     * @return bool
+     */
+    public function delete($name): bool
+    {
+        $this->writeTimes++;
+
+        return wincache_ucache_delete($this->getCacheKey($name));
+    }
+
+    /**
+     * 清除缓存
+     * @access public
+     * @return bool
+     */
+    public function clear(): bool
+    {
+        $this->writeTimes++;
+        return wincache_ucache_clear();
+    }
+
+    /**
+     * 删除缓存标签
+     * @access public
+     * @param array $keys 缓存标识列表
+     * @return void
+     */
+    public function clearTag(array $keys): void
+    {
+        wincache_ucache_delete($keys);
+    }
+
+}

+ 50 - 0
vendor/yiovo/tp6-cache/src/facade/Cache.php

@@ -0,0 +1,50 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace yiovo\cache\facade;
+
+use think\Facade;
+use yiovo\cache\cache\Driver;
+use yiovo\cache\cache\TagSet;
+
+/**
+ * @see \yiovo\cache\Cache
+ * @package yiovo\cache\facade
+ * @mixin \yiovo\cache\Cache
+ * @method static string|null getDefaultDriver() 默认驱动
+ * @method static mixed getConfig(null|string $name = null, mixed $default = null) 获取缓存配置
+ * @method static array getStoreConfig(string $store, string $name = null, null $default = null) 获取驱动配置
+ * @method static Driver store(string $name = null) 连接或者切换缓存
+ * @method static bool clear() 清空缓冲池
+ * @method static mixed get(string $key, mixed $default = null) 读取缓存
+ * @method static bool set(string $key, mixed $value, int|\DateTime $ttl = null) 写入缓存
+ * @method static bool delete(string $key) 删除缓存
+ * @method static iterable getMultiple(iterable $keys, mixed $default = null) 读取缓存
+ * @method static bool setMultiple(iterable $values, null|int|\DateInterval $ttl = null) 写入缓存
+ * @method static bool deleteMultiple(iterable $keys) 删除缓存
+ * @method static bool has(string $key) 判断缓存是否存在
+ * @method static TagSet tag(string|array $name) 缓存标签
+ * @method static mixed ttl(string $name) 获取缓存剩余有效期(秒)
+ * @method static mixed update(string $key, mixed $newVal = null, bool $isMerge = true) 更新缓存内容
+ */
+class Cache extends Facade
+{
+    /**
+     * 获取当前Facade对应类名(或者已经绑定的容器对象标识)
+     * @access protected
+     * @return string
+     */
+    protected static function getFacadeClass(): string
+    {
+        return \yiovo\cache\Cache::class;
+    }
+}

+ 5 - 0
vendor/yiovo/tp6-captcha/.gitignore

@@ -0,0 +1,5 @@
+/vendor
+/.idea
+composer.phar
+composer.lock
+.DS_Store

+ 191 - 0
vendor/yiovo/tp6-captcha/LICENSE

@@ -0,0 +1,191 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate
+notice, with the fields enclosed by brackets "{}" replaced with your own
+identifying information. (Don't include the brackets!) The text should be
+enclosed in the appropriate comment syntax for the file format. We also
+recommend that a file or class name and description of purpose be included on
+the same "printed page" as the copyright notice for easier identification within
+third-party archives.
+
+   Copyright 2018 萤火科技
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 3 - 0
vendor/yiovo/tp6-captcha/README.md

@@ -0,0 +1,3 @@
+# tp6-captcha
+
+thinkphp6 验证码

BIN
vendor/yiovo/tp6-captcha/assets/bgs/1.jpg


BIN
vendor/yiovo/tp6-captcha/assets/bgs/2.jpg


BIN
vendor/yiovo/tp6-captcha/assets/bgs/3.jpg


BIN
vendor/yiovo/tp6-captcha/assets/bgs/4.jpg


BIN
vendor/yiovo/tp6-captcha/assets/bgs/5.jpg


BIN
vendor/yiovo/tp6-captcha/assets/bgs/6.jpg


BIN
vendor/yiovo/tp6-captcha/assets/bgs/7.jpg


BIN
vendor/yiovo/tp6-captcha/assets/bgs/8.jpg


BIN
vendor/yiovo/tp6-captcha/assets/ttfs/1.ttf


BIN
vendor/yiovo/tp6-captcha/assets/ttfs/2.ttf


BIN
vendor/yiovo/tp6-captcha/assets/ttfs/3.ttf


BIN
vendor/yiovo/tp6-captcha/assets/ttfs/4.ttf


BIN
vendor/yiovo/tp6-captcha/assets/ttfs/5.ttf


BIN
vendor/yiovo/tp6-captcha/assets/ttfs/6.ttf


BIN
vendor/yiovo/tp6-captcha/assets/zhttfs/1.ttf


+ 31 - 0
vendor/yiovo/tp6-captcha/composer.json

@@ -0,0 +1,31 @@
+{
+  "name": "yiovo/tp6-captcha",
+  "description": "tp6-captcha",
+  "license": "Apache-2.0",
+  "authors": [
+    {
+      "name": "yiovo",
+      "email": "developer@yiovo.com"
+    }
+  ],
+  "require": {
+    "php": ">=7.1.0",
+    "ext-mbstring": "*",
+    "ext-gd": "*",
+    "topthink/framework": "^6.0.0",
+    "yiovo/tp6-cache": "^1.0"
+  },
+  "homepage": "https://github.com/yiovo/tp6-captcha",
+  "autoload": {
+    "psr-4": {
+      "yiovo\\captcha\\": "src/"
+    }
+  },
+  "extra": {
+    "think": {
+      "config": {
+        "captcha": "src/config.php"
+      }
+    }
+  }
+}

Datei-Diff unterdrückt, da er zu groß ist
+ 42 - 0
vendor/yiovo/tp6-captcha/src/Captcha.php


Datei-Diff unterdrückt, da er zu groß ist
+ 32 - 0
vendor/yiovo/tp6-captcha/src/CaptchaApi.php


+ 35 - 0
vendor/yiovo/tp6-captcha/src/config.php

@@ -0,0 +1,35 @@
+<?php
+// +----------------------------------------------------------------------
+// | Captcha配置文件
+// +----------------------------------------------------------------------
+
+return [
+    //验证码位数
+    'length' => 5,
+    // 验证码字符集合
+    'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY',
+    // 验证码过期时间
+    'expire' => 1800,
+    // 是否使用中文验证码
+    'useZh' => false,
+    // 是否使用算术验证码
+    'math' => false,
+    // 是否使用背景图
+    'useImgBg' => false,
+    //验证码字符大小
+    'fontSize' => 25,
+    // 是否使用混淆曲线
+    'useCurve' => true,
+    //是否添加杂点
+    'useNoise' => true,
+    // 验证码字体 不设置则随机
+    'fontttf' => '',
+    //背景颜色
+    'bg' => [243, 251, 254],
+    // 验证码图片高度
+    'imageH' => 0,
+    // 验证码图片宽度
+    'imageW' => 0,
+    // 验证码可重复验证的次数
+    'checkTimes' => 5,
+];

+ 20 - 0
vendor/yiovo/tp6-captcha/src/facade/Captcha.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace yiovo\captcha\facade;
+
+use think\Facade;
+
+/**
+ * Class Captcha
+ * @package yiovo\captcha\facade
+ * @mixin \yiovo\captcha\Captcha
+ * @method static array create(string $config = null) 生成图形验证码并把验证码的值保存的缓存中
+ * @method static bool check(string $code, string $key) 验证图形验证码是否正确
+ */
+class Captcha extends Facade
+{
+    protected static function getFacadeClass()
+    {
+        return \yiovo\captcha\Captcha::class;
+    }
+}

+ 22 - 0
vendor/yiovo/tp6-captcha/src/facade/CaptchaApi.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace yiovo\captcha\facade;
+
+use think\Facade;
+
+/**
+ * Class Captcha
+ * @package yiovo\captcha\facade
+ * @mixin \yiovo\captcha\CaptchaApi
+ * @method static array create(string $config = null) 生成图形验证码并把验证码的值保存的缓存中
+ * @method static bool check(string $code, string $key) 验证图形验证码是否正确
+ * @method static array createSMS(string $phone) 生成短信验证码并把验证码的值保存的缓存中
+ * @method static bool checkSMS(string $code, string $phone) 验证短信验证码是否正确
+ */
+class CaptchaApi extends Facade
+{
+    protected static function getFacadeClass()
+    {
+        return \yiovo\captcha\CaptchaApi::class;
+    }
+}

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.