diff --git a/.env.example b/.env.example index 8ccbe54..5ed72d5 100644 --- a/.env.example +++ b/.env.example @@ -15,3 +15,11 @@ REDIS_HOST=localhost REDIS_AUTH=(null) REDIS_PORT=6379 REDIS_DB=0 + +# 本机IP地址 +IP_ADDRESS=0.0.0.0 + +# 务必改为你自己的字符串 +JWT_SECRET=hyperf +#token过期时间,单位为秒 +JWT_TTL=60 diff --git a/app/Controller/AbstractController.php b/app/Controller/AbstractController.php index cab3ae8..5ba4ead 100644 --- a/app/Controller/AbstractController.php +++ b/app/Controller/AbstractController.php @@ -10,6 +10,7 @@ declare(strict_types=1); * @contact group@hyperf.io * @license https://github.com/hyperf/hyperf/blob/master/LICENSE */ + namespace App\Controller; use Hyperf\Di\Annotation\Inject; @@ -51,11 +52,11 @@ abstract class AbstractController * * @param mixed ...$arg */ - protected function validate(...$arg){ + protected function validate(...$arg) + { $validator = $this->validationFactory->make(...$arg); - if ($validator->fails()) { - throw new ValidateException($validator->errors()->first(),ResponseCode::VALIDATION_ERROR); + throw new ValidateException($validator->errors()->first(), ResponseCode::VALIDATION_ERROR); } } } diff --git a/app/Controller/Api/V1/ArticleController.php b/app/Controller/Api/V1/ArticleController.php index 4de471f..d17b0ff 100644 --- a/app/Controller/Api/V1/ArticleController.php +++ b/app/Controller/Api/V1/ArticleController.php @@ -1,12 +1,5 @@ validate($this->request->all(), [ + 'mobile' => "required|regex:/^1[345789][0-9]{9}$/", + 'password' => 'required', + 'platform' => 'required|in:h5,ios,windows,mac', + ],[ + 'mobile.regex'=>'mobile 格式不正确' + ]); + + $userInfo = $this->userService->login( + $this->request->input('mobile'), + $this->request->input('password') + ); + if (!$userInfo) { + return $this->response->fail('账号不存在或密码填写错误...', ResponseCode::FAIL); + } + + try { + $token = $this->jwt->getToken([ + 'user_id' => $userInfo['id'], + 'platform' => $this->request->input('platform'), + ]); + } catch (\Exception $exception) { + return $this->response->error('登录异常,请稍后再试...'); + } + + return $this->response->success([ + 'authorize' => [ + 'token' => $token, + 'expire' => $this->jwt->getTTL() + ], + 'user_info' => [ + 'nickname' => $userInfo['nickname'], + 'avatar' => $userInfo['avatar'], + 'gender' => $userInfo['gender'], + 'motto' => $userInfo['motto'], + 'email' => $userInfo['email'], + ] + ], '登录成功...'); + } + + /** + * 退出登录接口 + * + * @RequestMapping(path="logout", methods="get,post") + * @Middleware(JWTAuthMiddleware::class) + */ + public function logout() + { + $this->jwt->logout(); + + return $this->response->success([], 'Successfully logged out'); + } + + /** + * 账号注册接口 + */ + public function register() + { + + } + + /** + * 账号找回接口 + * + * @RequestMapping(path="forget", methods="post") + */ + public function forget() + { + + } + + /** + * 授权刷新接口 + * + * @RequestMapping(path="refresh", methods="post") + * @Middleware(JWTAuthMiddleware::class) + */ + public function refresh() + { + return $this->response->success([ + 'authorize' => [ + 'token' => $this->jwt->refreshToken(), + 'expire' => $this->jwt->getTTL() + ] + ], '刷新 Token 成功...'); + } } diff --git a/app/Controller/Api/V1/CController.php b/app/Controller/Api/V1/CController.php index 4dfa439..4437fde 100644 --- a/app/Controller/Api/V1/CController.php +++ b/app/Controller/Api/V1/CController.php @@ -3,8 +3,20 @@ namespace App\Controller\Api\V1; use App\Controller\AbstractController; +use App\Supports\Http\Response; +use Hyperf\Di\Annotation\Inject; +/** + * 基类控制器 + * + * Class CController + * @package App\Controller\Api\V1 + */ class CController extends AbstractController { - + /** + * @Inject + * @var Response + */ + protected $response; } diff --git a/app/Controller/Api/V1/EmoticonController.php b/app/Controller/Api/V1/EmoticonController.php index b12ef1c..5c39b66 100644 --- a/app/Controller/Api/V1/EmoticonController.php +++ b/app/Controller/Api/V1/EmoticonController.php @@ -1,12 +1,5 @@ logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile())); $this->logger->error($throwable->getTraceAsString()); diff --git a/app/Exception/Handler/JwtAuthExceptionHandler.php b/app/Exception/Handler/JwtAuthExceptionHandler.php new file mode 100644 index 0000000..d794bc6 --- /dev/null +++ b/app/Exception/Handler/JwtAuthExceptionHandler.php @@ -0,0 +1,44 @@ + $throwable->getCode(), + 'message' => $throwable->getMessage(), + 'data' => [] + ], JSON_UNESCAPED_UNICODE); + + // 阻止异常冒泡 + $this->stopPropagation(); + + return $response->withAddedHeader('content-type', 'application/json; charset=utf-8')->withStatus(401)->withBody(new SwooleStream($data)); + } + + return $response; + } + + /** + * 判断该异常处理器是否要对该异常进行处理 + */ + public function isValid(Throwable $throwable): bool + { + return true; + } +} diff --git a/app/Exception/Handler/ValidateExceptionHandler.php b/app/Exception/Handler/ValidateExceptionHandler.php index 5352b03..a22f59d 100644 --- a/app/Exception/Handler/ValidateExceptionHandler.php +++ b/app/Exception/Handler/ValidateExceptionHandler.php @@ -14,7 +14,7 @@ use Throwable; * Class ValidateExceptionHandler * @package App\Exception\Handler */ -class ValidateExceptionHandler extends ExceptionHandler +class ValidateExceptionHandler extends ExceptionHandler { public function handle(Throwable $throwable, ResponseInterface $response) { @@ -24,7 +24,7 @@ class ValidateExceptionHandler extends ExceptionHandler $data = json_encode([ 'code' => $throwable->getCode(), 'message' => $throwable->getMessage(), - 'data'=>[] + 'data' => [] ], JSON_UNESCAPED_UNICODE); // 阻止异常冒泡 diff --git a/app/Model/Model.php b/app/Model/Model.php index 40ca82e..06d375e 100644 --- a/app/Model/Model.php +++ b/app/Model/Model.php @@ -16,4 +16,5 @@ use Hyperf\DbConnection\Model\Model as BaseModel; abstract class Model extends BaseModel { + public $timestamps = false; } diff --git a/app/Model/User.php b/app/Model/User.php new file mode 100644 index 0000000..cf69704 --- /dev/null +++ b/app/Model/User.php @@ -0,0 +1,41 @@ +first(); + + if(!$user){ + return false; + } + + if(!password_verify($password,$user->password)){ + return false; + } + + return $user->toArray(); + } +} diff --git a/app/Services/UserService.php b/app/Services/UserService.php deleted file mode 100644 index 2cf2c22..0000000 --- a/app/Services/UserService.php +++ /dev/null @@ -1,8 +0,0 @@ -response = container()->get(ResponseInterface::class); - } - /** * @param $data * @return PsrResponseInterface @@ -69,26 +63,4 @@ class Response 'message' => $message, ]); } - - public function redirect($url, $status = 302) - { - return $this->response() - ->withAddedHeader('Location', (string)$url) - ->withStatus($status); - } - - public function cookie(Cookie $cookie) - { - $response = $this->response()->withCookie($cookie); - Context::set(PsrResponseInterface::class, $response); - return $this; - } - - /** - * @return \Hyperf\HttpMessage\Server\Response - */ - public function response() - { - return Context::get(PsrResponseInterface::class); - } } diff --git a/app/helper.php b/app/helper.php index abc14db..c8c058b 100644 --- a/app/helper.php +++ b/app/helper.php @@ -110,4 +110,14 @@ if (!function_exists('response')) { { return container()->get(ResponseInterface::class); } -} \ No newline at end of file +} + +/** + * 获取加密后的密码字符 + * + * @param string $password + * @return bool|false|null|string + */ +function create_password(string $password){ + return password_hash($password, PASSWORD_DEFAULT); +} diff --git a/composer.json b/composer.json index 6fc8086..d4a5799 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,9 @@ "hyperf/async-queue": "~2.0.0", "hyperf/amqp": "~2.0.0", "hyperf/websocket-server": "^2.0", - "hyperf/constants": "^2.0" + "hyperf/constants": "^2.0", + "hyperf/validation": "^2.0", + "phper666/jwt-auth": "^3.0" }, "require-dev": { "swoole/ide-helper": "^4.5", diff --git a/config/autoload/exceptions.php b/config/autoload/exceptions.php index b09be03..5c5c65e 100644 --- a/config/autoload/exceptions.php +++ b/config/autoload/exceptions.php @@ -15,6 +15,7 @@ return [ Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class, App\Exception\Handler\AppExceptionHandler::class, App\Exception\Handler\ValidateExceptionHandler::class, + App\Exception\Handler\JwtAuthExceptionHandler::class, ], ], ]; diff --git a/config/autoload/jwt.php b/config/autoload/jwt.php new file mode 100644 index 0000000..24a62fb --- /dev/null +++ b/config/autoload/jwt.php @@ -0,0 +1,115 @@ + env('JWT_LOGIN_TYPE', 'mpop'), // 登录方式,sso为单点登录,mpop为多点登录 + + /** + * 单点登录自定义数据中必须存在uid的键值,这个key你可以自行定义,只要自定义数据中存在该键即可 + */ + 'sso_key' => 'uid', + + 'secret' => env('JWT_SECRET', 'phper666'), // 非对称加密使用字符串,请使用自己加密的字符串 + + /** + * JWT 权限keys + * 对称算法: HS256, HS384 & HS512 使用 `JWT_SECRET`. + * 非对称算法: RS256, RS384 & RS512 / ES256, ES384 & ES512 使用下面的公钥私钥. + */ + 'keys' => [ + 'public' => env('JWT_PUBLIC_KEY'), // 公钥,例如:'file:///path/to/public/key' + 'private' => env('JWT_PRIVATE_KEY'), // 私钥,例如:'file:///path/to/private/key' + ], + + 'ttl' => env('JWT_TTL', 7200), // token过期时间,单位为秒 + + 'alg' => env('JWT_ALG', 'HS256'), // jwt的hearder加密算法 + + /** + * 支持的算法 + */ + 'supported_algs' => [ + 'HS256' => 'Lcobucci\JWT\Signer\Hmac\Sha256', + 'HS384' => 'Lcobucci\JWT\Signer\Hmac\Sha384', + 'HS512' => 'Lcobucci\JWT\Signer\Hmac\Sha512', + 'ES256' => 'Lcobucci\JWT\Signer\Ecdsa\Sha256', + 'ES384' => 'Lcobucci\JWT\Signer\Ecdsa\Sha384', + 'ES512' => 'Lcobucci\JWT\Signer\Ecdsa\Sha512', + 'RS256' => 'Lcobucci\JWT\Signer\Rsa\Sha256', + 'RS384' => 'Lcobucci\JWT\Signer\Rsa\Sha384', + 'RS512' => 'Lcobucci\JWT\Signer\Rsa\Sha512', + ], + + /** + * 对称算法名称 + */ + 'symmetry_algs' => [ + 'HS256', + 'HS384', + 'HS512' + ], + + /** + * 非对称算法名称 + */ + 'asymmetric_algs' => [ + 'RS256', + 'RS384', + 'RS512', + 'ES256', + 'ES384', + 'ES512', + ], + + /** + * 是否开启黑名单,单点登录和多点登录的注销、刷新使原token失效,必须要开启黑名单,目前黑名单缓存只支持hyperf缓存驱动 + */ + 'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true), + + /** + * 黑名单的宽限时间 单位为:秒,注意:如果使用单点登录,该宽限时间无效 + */ + 'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0), + + /** + * 黑名单缓存token时间,注意:该时间一定要设置比token过期时间要大一点,默认为1天,最好设置跟过期时间一样 + */ + 'blacklist_cache_ttl' => env('JWT_TTL', 86400), + + 'blacklist_prefix' => 'phper666_jwt', // 黑名单缓存的前缀 + + /** + * 区分不同场景的token,比如你一个项目可能会有多种类型的应用接口鉴权,下面自行定义,我只是举例子 + * 下面的配置会自动覆盖根配置,比如application1会里面的数据会覆盖掉根数据 + * 下面的scene会和根数据合并 + * scene必须存在一个default + * 什么叫根数据,这个配置的一维数组,除了scene都叫根配置 + */ + 'scene' => [ + 'default' => [], + 'application1' => [ + 'secret' => 'application1', // 非对称加密使用字符串,请使用自己加密的字符串 + 'login_type' => 'sso', // 登录方式,sso为单点登录,mpop为多点登录 + 'sso_key' => 'uid', + 'ttl' => 7200, // token过期时间,单位为秒 + 'blacklist_cache_ttl' => env('JWT_TTL', 7200), // 黑名单缓存token时间,注意:该时间一定要设置比token过期时间要大一点,默认为100秒,最好设置跟过期时间一样 + ], + 'application2' => [ + 'secret' => 'application2', // 非对称加密使用字符串,请使用自己加密的字符串 + 'login_type' => 'sso', // 登录方式,sso为单点登录,mpop为多点登录 + 'sso_key' => 'uid', + 'ttl' => 7200, // token过期时间,单位为秒 + 'blacklist_cache_ttl' => env('JWT_TTL', 7200), // 黑名单缓存token时间,注意:该时间一定要设置比token过期时间要大一点,默认为100秒,最好设置跟过期时间一样 + ], + 'application3' => [ + 'secret' => 'application3', // 非对称加密使用字符串,请使用自己加密的字符串 + 'login_type' => 'mppo', // 登录方式,sso为单点登录,mpop为多点登录 + 'ttl' => 7200, // token过期时间,单位为秒 + 'blacklist_cache_ttl' => env('JWT_TTL', 7200), // 黑名单缓存token时间,注意:该时间一定要设置比token过期时间要大一点,默认为100秒,最好设置跟过期时间一样 + ] + ], + 'model' => [ // TODO 支持直接获取某模型的数据 + 'class' => '', + 'pk' => 'uid' + ] +]; diff --git a/config/routes.php b/config/routes.php index 19fd53a..71264cf 100644 --- a/config/routes.php +++ b/config/routes.php @@ -18,6 +18,11 @@ Router::addRoute(['GET', 'POST', 'HEAD'], '/', 'App\Controller\IndexController@i Router::post('/upload', 'App\Controller\IndexController@upload',['middleware' => [CorsMiddleware::class]]); + + + + + Router::get('/favicon.ico', function () { return ''; }); diff --git a/migrations/2020_11_04_152602_create_users_table.php b/migrations/2020_11_04_152602_create_users_table.php new file mode 100644 index 0000000..860e8ee --- /dev/null +++ b/migrations/2020_11_04_152602_create_users_table.php @@ -0,0 +1,44 @@ +unsignedInteger('id', true)->comment('用户ID'); + $table->string('mobile', 11)->default('')->unique()->comment('手机号'); + $table->string('nickname', 20)->default('')->comment('用户昵称'); + $table->string('avatar', 255)->default('')->comment('用户头像地址'); + $table->unsignedTinyInteger('gender')->default(0)->unsigned()->comment('用户性别[0:未知;1:男;2:女]'); + $table->string('password', 255)->default('')->comment('用户密码'); + $table->string('motto', 100)->default('')->comment('用户座右铭'); + $table->string('email', 30)->default('')->comment('用户邮箱'); + $table->dateTime('created_at')->nullable()->comment('注册时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->unique(['mobile'], 'idx_mobile'); + }); + + $prefix = config('databases.default.prefix'); + Db::statement("ALTER TABLE `{$prefix}users` comment '用户信息表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users'); + } +} diff --git a/migrations/2020_11_04_153238_create_article_table.php b/migrations/2020_11_04_153238_create_article_table.php new file mode 100644 index 0000000..61c7bba --- /dev/null +++ b/migrations/2020_11_04_153238_create_article_table.php @@ -0,0 +1,48 @@ +unsignedInteger('id', true)->comment('笔记ID'); + $table->unsignedInteger('user_id')->default(0)->comment('用户ID'); + $table->unsignedInteger('class_id')->default(0)->comment('分类ID'); + $table->string('tags_id', 20)->default('')->comment('笔记关联标签'); + $table->string('title', 80)->default('')->charset('utf8mb4')->comment('笔记标题'); + $table->string('abstract', 200)->default('')->charset('utf8mb4')->comment('笔记摘要'); + $table->string('image', 255)->default('')->comment('笔记首图'); + $table->unsignedTinyInteger('is_asterisk')->default(0)->comment('是否星标笔记[0:否;1:是]'); + $table->unsignedTinyInteger('status')->default(1)->comment('笔记状态[1:正常;2:已删除]'); + $table->dateTime('created_at')->nullable(true)->comment('添加时间'); + $table->dateTime('updated_at')->nullable(true)->comment('最后一次更新时间'); + $table->dateTime('deleted_at')->nullable(true)->comment('笔记删除时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + //创建索引 + $table->index(['user_id', 'class_id', 'title'], 'idx_user_id_class_id_title'); + }); + + $prefix = config('databases.default.prefix'); + Db::statement("ALTER TABLE `{$prefix}article` comment '用户笔记表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('article'); + } +} diff --git a/migrations/2020_11_04_153251_create_article_annex_table.php b/migrations/2020_11_04_153251_create_article_annex_table.php new file mode 100644 index 0000000..abb6f82 --- /dev/null +++ b/migrations/2020_11_04_153251_create_article_annex_table.php @@ -0,0 +1,45 @@ +unsignedBigInteger('id', true)->comment('文件ID'); + $table->unsignedInteger('user_id')->unsigned()->comment('上传文件的用户ID'); + $table->unsignedInteger('article_id')->default(0)->comment('笔记ID'); + $table->string('file_suffix', 10)->default('')->comment('文件后缀名'); + $table->bigInteger('file_size')->default(0)->unsigned()->comment('文件大小(单位字节)'); + $table->string('save_dir', 500)->nullable()->comment('文件保存地址(相对地址)'); + $table->string('original_name', 100)->nullable()->comment('原文件名'); + $table->tinyInteger('status')->default(1)->unsigned()->comment('附件状态[1:正常;2:已删除]'); + $table->dateTime('created_at')->nullable(true)->comment('附件上传时间'); + $table->dateTime('deleted_at')->nullable(true)->comment('附件删除时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->index(['user_id', 'article_id'], 'idx_user_id_article_id'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}article_annex` comment '笔记附件信息表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('article_annex'); + } +} diff --git a/migrations/2020_11_04_153304_create_article_class_table.php b/migrations/2020_11_04_153304_create_article_class_table.php new file mode 100644 index 0000000..5a1a0fe --- /dev/null +++ b/migrations/2020_11_04_153304_create_article_class_table.php @@ -0,0 +1,40 @@ +unsignedInteger('id', true)->comment('笔记分类ID'); + $table->unsignedInteger('user_id')->default(0)->comment('用户ID'); + $table->string('class_name', 20)->default('')->comment('分类名'); + $table->unsignedTinyInteger('sort')->default(0)->comment('排序'); + $table->unsignedTinyInteger('is_default')->default(0)->comment('默认分类[1:是;0:不是]'); + $table->unsignedInteger('created_at')->nullable(true)->default(0)->comment('创建时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->index(['user_id', 'sort'], 'idx_user_id_sort'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}article_class` comment '笔记分类表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('article_class'); + } +} diff --git a/migrations/2020_11_04_153316_create_article_detail_table.php b/migrations/2020_11_04_153316_create_article_detail_table.php new file mode 100644 index 0000000..7ce9f4a --- /dev/null +++ b/migrations/2020_11_04_153316_create_article_detail_table.php @@ -0,0 +1,38 @@ +unsignedInteger('id', true)->comment('笔记详情ID'); + $table->unsignedInteger('article_id')->nullable(false)->comment('笔记ID'); + $table->longtext('md_content')->charset('utf8mb4')->comment('Markdown 内容'); + $table->longtext('content')->charset('utf8mb4')->comment('Markdown 解析HTML内容'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->unique('article_id', 'unique_article_id'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}article_detail` comment '笔记详情表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('article_detail'); + } +} diff --git a/migrations/2020_11_04_153327_create_article_tags_table.php b/migrations/2020_11_04_153327_create_article_tags_table.php new file mode 100644 index 0000000..1213e3c --- /dev/null +++ b/migrations/2020_11_04_153327_create_article_tags_table.php @@ -0,0 +1,38 @@ +unsignedInteger('id', true)->comment('笔记标签ID'); + $table->unsignedInteger('user_id')->default(0)->comment('用户ID'); + $table->string('tag_name', 20)->default('')->comment('标签名'); + $table->unsignedTinyInteger('sort')->default(0)->comment('排序'); + $table->unsignedInteger('created_at')->nullable(true)->default(0)->comment('创建时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + $table->index(['user_id'], 'idx_user_id'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}article_tags` comment '笔记标签表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('article_tags'); + } +} diff --git a/migrations/2020_11_04_153337_create_emoticon_table.php b/migrations/2020_11_04_153337_create_emoticon_table.php new file mode 100644 index 0000000..9976f8a --- /dev/null +++ b/migrations/2020_11_04_153337_create_emoticon_table.php @@ -0,0 +1,35 @@ +unsignedInteger('id', true)->comment('表情分组ID'); + $table->string('name', 100)->default('')->comment('表情分组名称'); + $table->string('url', 255)->default('')->comment('图片地址'); + $table->unsignedInteger('created_at')->nullable(true)->default(0)->comment('创建时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}emoticon` comment '表情包'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('emoticon'); + } +} diff --git a/migrations/2020_11_04_153347_create_emoticon_details_table.php b/migrations/2020_11_04_153347_create_emoticon_details_table.php new file mode 100644 index 0000000..2929bae --- /dev/null +++ b/migrations/2020_11_04_153347_create_emoticon_details_table.php @@ -0,0 +1,39 @@ +unsignedInteger('id', true)->comment('表情包ID'); + $table->unsignedInteger('emoticon_id')->default(0)->comment('表情分组ID'); + $table->unsignedInteger('user_id')->default(0)->comment('用户ID(0:代码系统表情包)'); + $table->string('describe', 20)->default('')->comment('表情关键字描述'); + $table->string('url', 255)->default('')->comment('表情链接'); + $table->string('file_suffix', 10)->default('')->comment('文件后缀名'); + $table->unsignedBigInteger('file_size')->default(0)->comment('文件大小(单位字节)'); + $table->unsignedInteger('created_at')->nullable(true)->default(0)->comment('添加时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}emoticon_details` comment '聊天表情包'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('emoticon_details'); + } +} diff --git a/migrations/2020_11_04_153358_create_file_split_upload_table.php b/migrations/2020_11_04_153358_create_file_split_upload_table.php new file mode 100644 index 0000000..df6b987 --- /dev/null +++ b/migrations/2020_11_04_153358_create_file_split_upload_table.php @@ -0,0 +1,45 @@ +unsignedInteger('id', true)->comment('临时文件ID'); + $table->unsignedTinyInteger('file_type')->default(2)->comment('数据类型[1:合并文件;2:拆分文件]'); + $table->unsignedInteger('user_id')->default(0)->comment('上传的用户ID'); + $table->string('hash_name', 30)->default('')->comment('临时文件hash名'); + $table->string('original_name', 100)->default('')->comment('原文件名'); + $table->unsignedTinyInteger('split_index')->default(0)->comment('当前索引块'); + $table->unsignedTinyInteger('split_num')->default(0)->comment('总上传索引块'); + $table->string('save_dir', 255)->default('')->comment('文件的临时保存路径'); + $table->string('file_ext', 10)->default('')->comment('文件后缀名'); + $table->unsignedInteger('file_size')->default(0)->comment('临时文件大小'); + $table->unsignedTinyInteger('is_delete')->default(0)->comment('文件是否已被删除[0:否;1:是]'); + $table->unsignedInteger('upload_at')->nullable(true)->comment('文件上传时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + + $table->index(['user_id', 'hash_name'], 'idx_user_id_hash_name'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}file_split_upload` comment '文件拆分上传'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('file_split_upload'); + } +} diff --git a/migrations/2020_11_04_153408_create_user_login_log_table.php b/migrations/2020_11_04_153408_create_user_login_log_table.php new file mode 100644 index 0000000..ef0c70d --- /dev/null +++ b/migrations/2020_11_04_153408_create_user_login_log_table.php @@ -0,0 +1,35 @@ +unsignedInteger('id', true)->comment('登录日志ID'); + $table->unsignedInteger('user_id')->default(0)->comment('用户ID'); + $table->string('ip', 20)->comment('登录地址IP'); + $table->dateTime('created_at')->nullable(true)->comment('登录时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}user_login_log` comment '用户登录日志表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('user_login_log'); + } +} diff --git a/migrations/2020_11_04_153421_create_users_chat_list_table.php b/migrations/2020_11_04_153421_create_users_chat_list_table.php new file mode 100644 index 0000000..eb88717 --- /dev/null +++ b/migrations/2020_11_04_153421_create_users_chat_list_table.php @@ -0,0 +1,44 @@ +unsignedInteger('id', true)->comment('聊天列表ID'); + $table->unsignedTinyInteger('type')->default(1)->comment('聊天类型[1:好友;2:群聊]'); + $table->unsignedInteger('uid')->default(0)->comment('用户ID'); + $table->unsignedInteger('friend_id')->default(0)->comment('朋友的用户ID'); + $table->unsignedInteger('group_id')->default(0)->comment('聊天分组ID'); + $table->unsignedInteger('status')->default(1)->default(1)->comment('状态[0:已删除;1:正常]'); + $table->unsignedTinyInteger('is_top')->default(0)->comment('是否置顶[0:否;1:是]'); + $table->unsignedTinyInteger('not_disturb')->default(0)->comment('是否消息免打扰[0:否;1:是]'); + $table->dateTime('created_at')->nullable(true)->comment('创建时间'); + $table->dateTime('updated_at')->nullable(true)->comment('更新时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->index(['uid', 'friend_id', 'group_id', 'type'], 'idx_uid_type_friend_id_group_id'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}users_chat_list` comment '用户聊天列表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users_chat_list'); + } +} diff --git a/migrations/2020_11_04_153431_create_chat_records_table.php b/migrations/2020_11_04_153431_create_chat_records_table.php new file mode 100644 index 0000000..f9c990d --- /dev/null +++ b/migrations/2020_11_04_153431_create_chat_records_table.php @@ -0,0 +1,42 @@ +unsignedInteger('id', true)->comment('聊天记录ID'); + $table->tinyInteger('source')->unsigned()->default(1)->comment('消息来源[1:好友消息;2:群聊消息]'); + $table->tinyInteger('msg_type')->unsigned()->default(1)->comment('消息类型[1:文本消息;2:文件消息;3:系统提示好友入群消息或系统提示好友退群消息;4:会话记录转发]'); + $table->unsignedInteger('user_id')->default(0)->comment('发送消息的用户ID[0:代表系统消息]'); + $table->unsignedInteger('receive_id')->default(0)->comment('接收消息的用户ID或群聊ID'); + $table->text('content')->nullable(true)->charset('utf8mb4')->comment('文本消息'); + $table->tinyInteger('is_revoke')->default(0)->comment('是否撤回消息[0:否;1:是]'); + $table->dateTime('created_at')->nullable(true)->comment('发送消息的时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->index(['user_id', 'receive_id'], 'idx_userid_receiveid'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}chat_records` comment '用户聊天记录表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('chat_records'); + } +} diff --git a/migrations/2020_11_04_153442_create_chat_records_file_table.php b/migrations/2020_11_04_153442_create_chat_records_file_table.php new file mode 100644 index 0000000..3f706a4 --- /dev/null +++ b/migrations/2020_11_04_153442_create_chat_records_file_table.php @@ -0,0 +1,46 @@ +unsignedInteger('id', true)->comment('文件ID'); + $table->unsignedInteger('record_id')->default(0)->comment('消息记录ID'); + $table->unsignedInteger('user_id')->default(0)->comment('上传文件的用户ID'); + $table->tinyInteger('file_source')->default(1)->unsigned()->comment('文件来源[1:用户上传;2:表情包]'); + $table->tinyInteger('file_type')->default(1)->unsigned()->comment('消息类型[1:图片;2:视频;3:文件]'); + $table->tinyInteger('save_type')->default(0)->unsigned()->comment('文件保存方式(0:本地 1:第三方[阿里OOS、七牛云] )'); + $table->string('original_name', 100)->default('')->comment('原文件名'); + $table->string('file_suffix', 10)->default('')->comment('文件后缀名'); + $table->unsignedBigInteger('file_size')->default(0)->comment('文件大小(单位字节)'); + $table->string('save_dir', 500)->default('')->comment('文件保存地址(相对地址/第三方网络地址)'); + $table->tinyInteger('is_delete')->default(0)->unsigned()->comment('文件是否已删除[0:否;1:已删除]'); + $table->dateTime('created_at')->nullable(true)->comment('创建时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->unique(['record_id'], 'idx_record_id'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}chat_records_file` comment '用户聊天记录_文件消息表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('chat_records_file'); + } +} diff --git a/migrations/2020_11_04_153453_create_chat_records_delete_table.php b/migrations/2020_11_04_153453_create_chat_records_delete_table.php new file mode 100644 index 0000000..9cd4ef9 --- /dev/null +++ b/migrations/2020_11_04_153453_create_chat_records_delete_table.php @@ -0,0 +1,39 @@ +unsignedInteger('id', true)->comment('聊天删除记录ID'); + $table->unsignedInteger('record_id')->default(0)->comment('聊天记录ID'); + $table->unsignedInteger('user_id')->default(0)->comment('用户ID'); + $table->dateTime('created_at')->nullable(true)->comment('删除时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->index(['record_id', 'user_id'], 'idx_record_user_id'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}chat_records_delete` comment '用户聊天记录_删除记录表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('chat_records_delete_file'); + } +} diff --git a/migrations/2020_11_04_153504_create_chat_records_forward_table.php b/migrations/2020_11_04_153504_create_chat_records_forward_table.php new file mode 100644 index 0000000..383f859 --- /dev/null +++ b/migrations/2020_11_04_153504_create_chat_records_forward_table.php @@ -0,0 +1,40 @@ +unsignedInteger('id', true)->comment('合并转发ID'); + $table->unsignedInteger('record_id')->default(0)->comment('消息记录ID'); + $table->unsignedInteger('user_id')->default(0)->comment('转发用户ID'); + $table->string('records_id', 255)->default('')->comment("转发的聊天记录ID,多个用','分割"); + $table->json('text')->default(null)->comment('记录快照'); + $table->dateTime('created_at')->nullable(true)->comment('转发时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->index(['user_id', 'records_id'], 'idx_user_id_records_id'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}chat_records_forward` comment '用户聊天记录_转发信息表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('chat_records_forward'); + } +} diff --git a/migrations/2020_11_04_153516_create_chat_records_invite_table.php b/migrations/2020_11_04_153516_create_chat_records_invite_table.php new file mode 100644 index 0000000..f3223c0 --- /dev/null +++ b/migrations/2020_11_04_153516_create_chat_records_invite_table.php @@ -0,0 +1,39 @@ +unsignedInteger('id', true)->comment('入群或退群通知ID'); + $table->unsignedInteger('record_id')->default(0)->comment('消息记录ID'); + $table->tinyInteger('type')->default(1)->comment('通知类型[1:入群通知;2:自动退群;3:管理员踢群]'); + $table->unsignedInteger('operate_user_id')->default(0)->comment('操作人的用户ID(邀请人)'); + $table->string('user_ids', 255)->default('')->comment("用户ID,多个用','分割"); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->index(['record_id'], 'idx_recordid'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}chat_records_invite` comment '用户聊天记录_入群或退群消息表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('chat_records_invite'); + } +} diff --git a/migrations/2020_11_04_153529_create_chat_records_code_table.php b/migrations/2020_11_04_153529_create_chat_records_code_table.php new file mode 100644 index 0000000..d3ed216 --- /dev/null +++ b/migrations/2020_11_04_153529_create_chat_records_code_table.php @@ -0,0 +1,40 @@ +unsignedInteger('id', true)->comment('入群或退群通知ID'); + $table->unsignedInteger('record_id')->default(0)->comment('消息记录ID'); + $table->unsignedInteger('user_id')->default(0)->comment('上传文件的用户ID'); + $table->string('code_lang', 20)->default('')->comment("代码片段类型(如:php,java,python)"); + $table->text('code')->charset('utf8mb4')->comment('代码片段内容'); + $table->dateTime('created_at')->nullable(true)->comment('创建时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->index(['record_id'], 'idx_recordid'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}chat_records_code` comment '用户聊天记录_代码块消息表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('chat_records_code'); + } +} diff --git a/migrations/2020_11_04_153541_create_users_emoticon_table.php b/migrations/2020_11_04_153541_create_users_emoticon_table.php new file mode 100644 index 0000000..cd268db --- /dev/null +++ b/migrations/2020_11_04_153541_create_users_emoticon_table.php @@ -0,0 +1,36 @@ +unsignedInteger('id', true)->comment('表情包收藏ID'); + $table->unsignedInteger('user_id')->default(0)->unique()->comment('用户ID'); + $table->string('emoticon_ids', 255)->default('')->comment('表情包ID'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + + $table->index(['user_id'], 'idx_user_id'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}users_emoticon` comment '用户收藏表情包'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users_emoticon'); + } +} diff --git a/migrations/2020_11_04_153553_create_users_friends_table.php b/migrations/2020_11_04_153553_create_users_friends_table.php new file mode 100644 index 0000000..a1f6396 --- /dev/null +++ b/migrations/2020_11_04_153553_create_users_friends_table.php @@ -0,0 +1,43 @@ +unsignedInteger('id', true)->comment('关系ID'); + $table->unsignedInteger('user1')->default(0)->comment('用户1(user1 一定比 user2 小)'); + $table->unsignedInteger('user2')->default(0)->comment('用户2(user1 一定比 user2 小)'); + $table->string('user1_remark', 20)->default('')->comment('好友备注'); + $table->string('user2_remark', 20)->default('')->comment('好友备注'); + $table->unsignedTinyInteger('active')->default(1)->default(1)->comment('主动邀请方[1:user1;2:user2]'); + $table->unsignedTinyInteger('status')->default(1)->comment('好友状态[0:已解除好友关系;1:好友状态]'); + $table->dateTime('agree_time')->comment('成为好友时间'); + $table->dateTime('created_at')->nullable(true)->comment('创建时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->index(['user1', 'user2'], 'idx_user1_user2'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}users_friends` comment '用户好友关系表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users_friends'); + } +} diff --git a/migrations/2020_11_04_153605_create_users_friends_apply_table.php b/migrations/2020_11_04_153605_create_users_friends_apply_table.php new file mode 100644 index 0000000..6403f8a --- /dev/null +++ b/migrations/2020_11_04_153605_create_users_friends_apply_table.php @@ -0,0 +1,42 @@ +unsignedInteger('id', true)->comment('申请ID'); + $table->unsignedInteger('user_id')->default(0)->comment('申请人ID'); + $table->unsignedInteger('friend_id')->default(0)->comment('被申请人'); + $table->unsignedTinyInteger('status')->default(0)->comment('申请状态[0:等待处理;1:已同意]'); + $table->string('remarks', 50)->default('')->comment('申请人备注信息'); + $table->dateTime('created_at')->nullable()->comment('申请时间'); + $table->dateTime('updated_at')->nullable()->comment('处理时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->index(['user_id'], 'idx_user_id'); + $table->index(['friend_id'], 'idx_friend_id'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}users_friends_apply` comment '用户添加好友申请表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users_friends_apply'); + } +} diff --git a/migrations/2020_11_04_153616_create_users_group_table.php b/migrations/2020_11_04_153616_create_users_group_table.php new file mode 100644 index 0000000..eb60d8e --- /dev/null +++ b/migrations/2020_11_04_153616_create_users_group_table.php @@ -0,0 +1,35 @@ +unsignedInteger('id', true)->comment('群ID'); + $table->unsignedInteger('user_id')->default(0)->comment('用户ID'); + $table->string('group_name', 30)->default('')->charset('utf8mb4')->comment('群名称'); + $table->string('group_profile', 100)->default('')->comment('群介绍'); + $table->tinyInteger('status')->default(0)->comment('群状态[0:正常;1:已解散]'); + $table->string('avatar', 255)->default('')->comment('群头像'); + $table->dateTime('created_at')->nullable()->comment('创建时间'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}users_group` comment '用户聊天群'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users_group'); + } +} diff --git a/migrations/2020_11_04_153626_create_users_group_member_table.php b/migrations/2020_11_04_153626_create_users_group_member_table.php new file mode 100644 index 0000000..397520e --- /dev/null +++ b/migrations/2020_11_04_153626_create_users_group_member_table.php @@ -0,0 +1,41 @@ +unsignedInteger('id', true)->comment('自增ID'); + $table->unsignedInteger('group_id')->default(0)->comment('群ID'); + $table->unsignedInteger('user_id')->default(0)->comment('用户ID'); + $table->tinyInteger('group_owner')->nullable()->comment('是否为群主[0:否;1:是]'); + $table->tinyInteger('status')->default(0)->comment('退群状态[0:正常状态;1:已退群]'); + $table->string('visit_card', 20)->default('')->comment('用户群名片'); + $table->dateTime('created_at')->nullable()->comment('入群时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->index(['group_id', 'status'], 'idx_group_id_status'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}users_group_member` comment '群聊成员'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users_group_member'); + } +} diff --git a/migrations/2020_11_04_153636_create_users_group_notice_table.php b/migrations/2020_11_04_153636_create_users_group_notice_table.php new file mode 100644 index 0000000..3538109 --- /dev/null +++ b/migrations/2020_11_04_153636_create_users_group_notice_table.php @@ -0,0 +1,43 @@ +unsignedInteger('id', true)->comment('公告ID'); + $table->unsignedInteger('group_id')->default(0)->comment('群ID'); + $table->unsignedInteger('user_id')->default(0)->comment('创建者用户ID'); + $table->string('title', 30)->default('')->charset('utf8mb4')->comment('公告标题'); + $table->text('content')->charset('utf8mb4')->comment('公告内容'); + $table->tinyInteger('is_delete')->default(0)->comment('是否删除[0:否;1:已删除]'); + $table->dateTime('created_at')->nullable()->comment('创建时间'); + $table->dateTime('updated_at')->nullable()->comment('更新时间'); + $table->dateTime('deleted_at')->nullable()->comment('删除时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + + $table->index(['group_id'], 'idx_group_id'); + }); + + $prefix = config('databases.default.prefix'); + DB::statement("ALTER TABLE `{$prefix}users_group_notice` comment '群组公告表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users_group_notice'); + } +} diff --git a/test.php b/test.php new file mode 100644 index 0000000..462102d --- /dev/null +++ b/test.php @@ -0,0 +1,10 @@ +