diff --git a/Makefile b/Makefile
index 506c463..b0fd7d6 100644
--- a/Makefile
+++ b/Makefile
@@ -2,3 +2,7 @@
dockerimage:
@echo "building Jump Jump docker image..."
docker build -t studiomj/jump-jump:latest -f build/package/Dockerfile .
+
+.PHONY: docs
+docs:
+ swag init -g ./internal/app/routers/router.go
\ No newline at end of file
diff --git a/README.md b/README.md
index dab758e..9560806 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,7 @@
* [设置短链接域名](#设置短链接域名)
* [获取完整短链接](#获取完整短链接)
* [部署到服务器](#部署到服务器)
+* [接口文档](#接口文档)
* [感谢](#感谢)
---
@@ -100,6 +101,11 @@ docker-compose -f deployments/docker-compose.yaml -p jumpjump exec apiserver ./c
这里提供了使用 docker-compose 的部署方案,[点击查看](http://t.majiawei.com/fk1ta3)。
+## 接口文档
+
+使用 Swagger UI 提供了一个可调试文档,具体使用方法查看这个 [PR](https://github.com/jwma/jump-jump/pull/40),希望这份文档能够帮助
+到大家!
+
## 感谢
在这里感谢所有为 Jump Jump 提供建议和反馈 bug 的朋友们,有你们 Jump Jump 会变得更好!
diff --git a/api/config/v1/basics.http b/api/config/v1/basics.http
deleted file mode 100644
index 81180ad..0000000
--- a/api/config/v1/basics.http
+++ /dev/null
@@ -1,85 +0,0 @@
-# 获取配置
-GET http://{{host}}/v1/config
-
-> {%
- client.test('Get config successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
-
-# 用户登入
-POST http://{{host}}/v1/user/login
-Content-Type: application/json
-
-{
- "username": "{{adminUsername}}",
- "password": "{{adminPassword}}"
-}
-
-> {%
- client.test('Login successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
- client.global.set('token', 'Bearer ' + response.body.data.token);
-%}
-
-###
-
-# 更新 landingHosts 配置
-PATCH http://{{host}}/v1/config/landing-hosts
-Content-Type: application/json
-Authorization: {{token}}
-
-{
- "hosts": [
- "http://127.0.0.1:8081/"
- ]
-}
-
-> {%
- client.test('Update landing successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
-
-# 更新随机 ID 长度设置
-PATCH http://{{host}}/v1/config/id-length
-Content-Type: application/json
-Authorization: {{token}}
-
-{
- "idMinimumLength": 6,
- "idLength": 8,
- "idMaximumLength": 10
-}
-
-> {%
- client.test('Update landing successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
-
-# 更新短链接 404 处理配置
-PATCH http://{{host}}/v1/config/short-link-404-handling
-Content-Type: application/json
-Authorization: {{token}}
-
-{
- "mode": "redirect",
- "value": "https://www.google.com"
-}
-
-> {%
- client.test('Update landing successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- client.assert(0 === response.body.code, 'Want 0, but got ' + response.body.code);
- });
-%}
-
-###
\ No newline at end of file
diff --git a/api/http-client.env.json b/api/http-client.env.json
deleted file mode 100644
index 47097dc..0000000
--- a/api/http-client.env.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "dev": {
- "host": "127.0.0.1:8080",
- "username": "",
- "password": "",
- "adminUsername": "",
- "adminPassword": ""
- }
-}
\ No newline at end of file
diff --git a/api/shortlink/v1/base-cases.http b/api/shortlink/v1/base-cases.http
deleted file mode 100644
index 6f25940..0000000
--- a/api/shortlink/v1/base-cases.http
+++ /dev/null
@@ -1,120 +0,0 @@
-# 短链接管理接口基础测试
-
-# 1. 用户登入
-POST http://{{host}}/v1/user/login
-Content-Type: application/json
-
-{
- "username": "{{username}}",
- "password": "{{password}}"
-}
-
-> {%
- client.test('Login successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
- client.global.set('token', 'Bearer ' + response.body.data.token);
-%}
-
-###
-
-# 2. 创建短链接
-POST http://{{host}}/v1/short-link/
-Content-Type: application/json
-Authorization: {{token}}
-
-{
- "url": "http://anmuji.com/?t={{$timestamp}}",
- "description": "{{$uuid}}",
- "is_enable": true
-}
-
-> {%
- client.test('Create short link successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
- client.global.set("short_link_id", response.body.data.shortLink.id);
-%}
-
-###
-
-# 3. 获取短链接
-GET http://{{host}}/v1/short-link/{{short_link_id}}
-Content-Type: application/json
-Authorization: {{token}}
-
-> {%
- client.test('Get short link successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
-
-# 4. 获取短链接最近的访问历史
-GET http://{{host}}/v1/short-link/{{short_link_id}}/latest-request-history
-Content-Type: application/json
-Authorization: {{token}}
-
-> {%
- client.test('Get short link history successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
-
-# 5. 更新短链接
-PATCH http://{{host}}/v1/short-link/{{short_link_id}}
-Content-Type: application/json
-Authorization: {{token}}
-
-{
- "url": "http://anmuji.com",
- "description": "{{$uuid}}",
- "isEnable": true
-}
-
-> {%
- client.test('Update short link successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
-
-# 6. 删除短链接
-DELETE http://{{host}}/v1/short-link/{{short_link_id}}
-Authorization: {{token}}
-
-> {%
- client.test('Delete short link successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
-
-# 7. 重复删除短链接
-DELETE http://{{host}}/v1/short-link/{{short_link_id}}
-Authorization: {{token}}
-
-> {%
- client.test('Delete short link failed', function() {
- client.assert(4999 === response.body.code, 'Want 4999, but got ' + response.body.code);
- });
-%}
-
-###
-
-# 8. 获取短链接列表
-GET http://{{host}}/v1/short-link/
-Authorization: {{token}}
-
-> {%
- client.test('List short links successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
\ No newline at end of file
diff --git a/api/shortlink/v1/test-role.http b/api/shortlink/v1/test-role.http
deleted file mode 100644
index 8374223..0000000
--- a/api/shortlink/v1/test-role.http
+++ /dev/null
@@ -1,164 +0,0 @@
-# 1. 使用 RoleUser 角色的用户登入
-POST http://{{host}}/v1/user/login
-Content-Type: application/json
-
-{
- "username": "{{username}}",
- "password": "{{password}}"
-}
-
-> {%
- client.test('Login successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
- client.global.set('token', 'Bearer ' + response.body.data.token);
-%}
-
-###
-
-# 2. 使用 RoleAdmin 角色的用户登入
-POST http://{{host}}/v1/user/login
-Content-Type: application/json
-
-{
- "username": "{{adminUsername}}",
- "password": "{{adminPassword}}"
-}
-
-> {%
- client.test('Login successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
- client.global.set('admin_token', 'Bearer ' + response.body.data.token);
-%}
-
-###
-
-# 3. 使用 token 请求创建短链接接口
-POST http://{{host}}/v1/short-link/
-Content-Type: application/json
-Authorization: {{token}}
-
-{
- "url": "http://anmuji.com/?t={{$timestamp}}",
- "description": "{{$uuid}}",
- "is_enable": true
-}
-
-> {%
- client.test('Create short link successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
- client.global.set('user_shortlink_id', response.body.data.shortLink.id);
-%}
-
-###
-
-# 4. 使用 admin_token 请求创建短链接接口
-POST http://{{host}}/v1/short-link/
-Content-Type: application/json
-Authorization: {{admin_token}}
-
-{
- "url": "http://anmuji.com/?t={{$timestamp}}",
- "description": "{{$uuid}}",
- "is_enable": true
-}
-
-> {%
- client.test('Create short link successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
- client.global.set('admin_shortlink_id', response.body.data.shortLink.id);
-%}
-
-###
-
-# 5. 使用 token 获取使用 token 创建的短链接
-GET http://{{host}}/v1/short-link/{{user_shortlink_id}}/
-Content-Type: application/json
-Authorization: {{token}}
-
-> {%
- client.test('Get short link successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
-
-# 6. 使用 token 获取使用 admin_token 所创建的短链接
-GET http://{{host}}/v1/short-link/{{admin_shortlink_id}}/
-Content-Type: application/json
-Authorization: {{token}}
-
-> {%
- client.test('Get admin short link failed', function() {
- client.assert(4999 === response.body.code, 'Want 4999, but got ' + response.body.code);
- });
-%}
-
-###
-
-# 7. 使用 token 更新使用 token 创建的短链接
-PATCH http://{{host}}/v1/short-link/{{user_shortlink_id}}
-Content-Type: application/json
-Authorization: {{token}}
-
-{
- "url": "http://anmuji.com",
- "description": "{{$uuid}}",
- "isEnable": true
-}
-
-> {%
- client.test('Update user short link successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
-
-# 8. 使用 token 更新使用 admin_token 创建的短链接
-# 期望返回 403
-PATCH http://{{host}}/v1/short-link/{{admin_shortlink_id}}
-Content-Type: application/json
-Authorization: {{token}}
-
-{
- "url": "http://anmuji.com",
- "description": "{{$uuid}}",
- "isEnable": true
-}
-
-> {%
- client.test('Update admin short link failed', function() {
- client.assert(4999 === response.body.code, 'Want 4999, but got ' + response.body.code);
- });
-%}
-
-###
-
-# 9. 使用 token 删除使用 token 创建的短链接
-DELETE http://{{host}}/v1/short-link/{{user_shortlink_id}}
-Authorization: {{token}}
-
-> {%
- client.test('Delete short link successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
-
-# 10. 使用 token 删除使用 admin_token 创建的短链接
-DELETE http://{{host}}/v1/short-link/{{admin_shortlink_id}}
-Authorization: {{token}}
-
-> {%
- client.test('Delete short link failed', function() {
- client.assert(4999 === response.body.code, 'Want 4999, but got ' + response.body.code);
- });
-%}
-
-###
\ No newline at end of file
diff --git a/api/user/v1/test-change-password.http b/api/user/v1/test-change-password.http
deleted file mode 100644
index a3a5834..0000000
--- a/api/user/v1/test-change-password.http
+++ /dev/null
@@ -1,88 +0,0 @@
-# 1. 登入
-POST http://{{host}}/v1/user/login
-Content-Type: application/json
-
-{
- "username": "{{username}}",
- "password": "{{password}}"
-}
-
-> {%
- client.test('Login successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
- client.global.set('token', 'Bearer ' + response.body.data.token);
-%}
-
-###
-
-# 2. 修改密码
-PATCH http://{{host}}/v1/user/change-password
-Content-Type: application/json
-Authorization: {{token}}
-
-{
- "password": "{{password}}",
- "newPassword": "123456"
-}
-
-> {%
- client.test('Change password successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
-
-# 3. 使用旧密码登入失败
-POST http://{{host}}/v1/user/login
-Content-Type: application/json
-
-{
- "username": "{{username}}",
- "password": "{{password}}"
-}
-
-> {%
- client.test('Login with old password failed', function() {
- client.assert(4999 === response.body.code, 'Want 4999, but got ' + response.body.code);
- });
-%}
-
-###
-
-# 4. 使用新密码登入成功
-POST http://{{host}}/v1/user/login
-Content-Type: application/json
-
-{
- "username": "{{username}}",
- "password": "123456"
-}
-
-> {%
- client.test('Login with new password successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
- client.global.set('token', 'Bearer ' + response.body.data.token);
-%}
-
-###
-
-# 5. 改回旧密码
-PATCH http://{{host}}/v1/user/change-password
-Content-Type: application/json
-Authorization: {{token}}
-
-{
- "password": "123456",
- "newPassword": "{{password}}"
-}
-
-> {%
- client.test('Reset password to old password successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
diff --git a/api/user/v1/user.http b/api/user/v1/user.http
deleted file mode 100644
index 36fd2f6..0000000
--- a/api/user/v1/user.http
+++ /dev/null
@@ -1,16 +0,0 @@
-# 登入
-POST http://{{host}}/v1/user/login
-Content-Type: application/json
-
-{
- "username": "{{adminUsername}}",
- "password": "{{adminPassword}}"
-}
-
-> {%
- client.test('Login successfully', function() {
- client.assert(200 === response.status, 'Want 200, but got ' + response.status);
- });
-%}
-
-###
\ No newline at end of file
diff --git a/docs/docs.go b/docs/docs.go
new file mode 100644
index 0000000..76222dc
--- /dev/null
+++ b/docs/docs.go
@@ -0,0 +1,1129 @@
+// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+// This file was generated by swaggo/swag
+
+package docs
+
+import (
+ "bytes"
+ "encoding/json"
+ "strings"
+
+ "github.com/alecthomas/template"
+ "github.com/swaggo/swag"
+)
+
+var doc = `{
+ "schemes": {{ marshal .Schemes }},
+ "swagger": "2.0",
+ "info": {
+ "description": "{{.Description}}",
+ "title": "{{.Title}}",
+ "contact": {
+ "name": "MJ Ma",
+ "url": "https://www.linkedin.com/in/mj-profile/",
+ "email": "m.mjw.ma@gmail.com"
+ },
+ "license": {
+ "name": "MIT",
+ "url": "https://github.com/jwma/jump-jump/blob/master/LICENSE"
+ },
+ "version": "{{.Version}}"
+ },
+ "host": "{{.Host}}",
+ "basePath": "{{.BasePath}}",
+ "paths": {
+ "/config": {
+ "get": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "获取系统配置信息",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "系统配置"
+ ],
+ "summary": "获取系统配置信息",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/GetConfigAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/config/id-length": {
+ "patch": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "更新短链接 ID 设置",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "系统配置"
+ ],
+ "summary": "更新短链接 ID 设置",
+ "parameters": [
+ {
+ "description": "更新短链接 ID 设置请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/IdConfig"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/GetConfigAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/config/landing-hosts": {
+ "patch": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "更新落地页 Hosts",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "系统配置"
+ ],
+ "summary": "更新落地页 Hosts",
+ "parameters": [
+ {
+ "description": "更新落地页 Hosts 请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/UpdateLandingHostsAPIRequest"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/GetConfigAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/config/short-link-404-handling": {
+ "patch": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "更新短链接 404 设置",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "系统配置"
+ ],
+ "summary": "更新短链接 404 设置",
+ "parameters": [
+ {
+ "description": "更新短链接 404 设置请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/ShortLinkNotFoundConfig"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/GetConfigAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/short-link/": {
+ "get": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "短链接列表",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "短链接"
+ ],
+ "summary": "短链接列表",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "页码",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "每页条数",
+ "name": "pageSize",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/ListShortLinksAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ },
+ "post": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "创建短链接",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "短链接"
+ ],
+ "summary": "创建短链接",
+ "parameters": [
+ {
+ "description": "创建短链接请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateShortLinkAPIRequest"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/CreateShortLinkAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/short-link/{id}": {
+ "get": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "获取系统配置信息",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "短链接"
+ ],
+ "summary": "获取指定 ID 短链接",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "短链接 ID",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/GetShortLinkAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ },
+ "delete": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "删除短链接",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "短链接"
+ ],
+ "summary": "删除短链接",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "短链接 ID",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/Response"
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ },
+ "patch": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "更新短链接",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "短链接"
+ ],
+ "summary": "更新短链接",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "短链接 ID",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "description": "更新短链接请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/UpdateShortLinkAPIRequest"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/UpdateShortLinkAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/short-link/{id}/data": {
+ "get": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "可查询短链接某个日期范围内的访问数据",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "短链接"
+ ],
+ "summary": "短链接访问数据",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "短链接 ID",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "开始日期 YYYY-mm-dd",
+ "name": "startDate",
+ "in": "query",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "结束日期 YYYY-mm-dd",
+ "name": "endDate",
+ "in": "query",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/ShortLinkDataAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/user/change-password": {
+ "post": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "修改账号密码",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "账号"
+ ],
+ "summary": "修改账号密码",
+ "parameters": [
+ {
+ "description": "修改密码请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/ChangePasswordAPIRequest"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/Response"
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/user/info": {
+ "get": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "获取账号信息",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "账号"
+ ],
+ "summary": "获取账号信息",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/GetUserInfoAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/user/login": {
+ "post": {
+ "description": "账号密码登入",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "账号"
+ ],
+ "summary": "账号登入",
+ "parameters": [
+ {
+ "description": "登入请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/LoginAPIRequest"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/LoginAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "/user/logout": {
+ "post": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "登出",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "账号"
+ ],
+ "summary": "登出",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/Response"
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "ChangePasswordAPIRequest": {
+ "type": "object",
+ "properties": {
+ "newPassword": {
+ "description": "新密码",
+ "type": "string"
+ },
+ "password": {
+ "description": "原密码",
+ "type": "string"
+ }
+ }
+ },
+ "CreateShortLinkAPIRequest": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "description": "描述",
+ "type": "string",
+ "example": "Jump Jump project"
+ },
+ "id": {
+ "description": "只有管理员可以在创建的时候指定 ID",
+ "type": "string",
+ "format": "string",
+ "example": "RANDOM_ID"
+ },
+ "idLength": {
+ "description": "短链接 ID 长度",
+ "type": "integer",
+ "format": "int",
+ "example": 4
+ },
+ "isEnable": {
+ "description": "是否启用",
+ "type": "boolean",
+ "format": "boolean",
+ "example": true
+ },
+ "url": {
+ "description": "目标链接",
+ "type": "string",
+ "example": "https://github.com/jwma/jump-jump"
+ }
+ }
+ },
+ "CreateShortLinkAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "shortLink": {
+ "$ref": "#/definitions/ShortLinkData"
+ }
+ }
+ },
+ "GetConfigAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "config": {
+ "$ref": "#/definitions/SystemConfig"
+ }
+ }
+ },
+ "GetShortLinkAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "shortLink": {
+ "$ref": "#/definitions/ShortLinkData"
+ }
+ }
+ },
+ "GetUserInfoAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "role": {
+ "description": "角色,1 普通用户 | 2 管理员",
+ "type": "integer",
+ "enum": [
+ 1,
+ 2
+ ],
+ "example": 1
+ },
+ "username": {
+ "description": "用户名",
+ "type": "string",
+ "example": "admin"
+ }
+ }
+ },
+ "IdConfig": {
+ "type": "object",
+ "properties": {
+ "idLength": {
+ "description": "ID 长度",
+ "type": "integer",
+ "format": "int",
+ "example": 6
+ },
+ "idMaximumLength": {
+ "description": "最大 ID 长度",
+ "type": "integer",
+ "format": "int",
+ "example": 10
+ },
+ "idMinimumLength": {
+ "description": "最小 ID 长度",
+ "type": "integer",
+ "format": "int",
+ "example": 2
+ }
+ }
+ },
+ "ListShortLinksAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "shortLinks": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/ShortLinkData"
+ }
+ },
+ "total": {
+ "type": "integer",
+ "format": "10",
+ "example": 10
+ }
+ }
+ },
+ "LoginAPIRequest": {
+ "type": "object",
+ "required": [
+ "password",
+ "username"
+ ],
+ "properties": {
+ "password": {
+ "description": "密码",
+ "type": "string",
+ "example": "your_password"
+ },
+ "username": {
+ "description": "用户名",
+ "type": "string",
+ "example": "your_username"
+ }
+ }
+ },
+ "LoginAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "token": {
+ "description": "json web token",
+ "type": "string",
+ "example": "xxx.xxx.xxx"
+ }
+ }
+ },
+ "RequestHistory": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "ip": {
+ "type": "string"
+ },
+ "time": {
+ "type": "string"
+ },
+ "ua": {
+ "type": "string"
+ },
+ "url": {
+ "description": "由于短链接的目标连接可能会被修改,可以在访问历史记录中记录一下当前的目标连接",
+ "type": "string"
+ }
+ }
+ },
+ "Response": {
+ "type": "object",
+ "properties": {
+ "code": {
+ "type": "integer",
+ "format": "int",
+ "default": 0,
+ "example": 0
+ },
+ "data": {
+ "type": "object"
+ },
+ "msg": {
+ "type": "string",
+ "default": "ok",
+ "example": "ok"
+ }
+ }
+ },
+ "ShortLinkData": {
+ "type": "object",
+ "properties": {
+ "createTime": {
+ "description": "创建时间",
+ "type": "string"
+ },
+ "createdBy": {
+ "description": "创建者",
+ "type": "string",
+ "format": "string",
+ "example": "admin"
+ },
+ "description": {
+ "description": "描述",
+ "type": "string",
+ "format": "string",
+ "example": "Jump Jump project"
+ },
+ "id": {
+ "type": "string",
+ "format": "string",
+ "example": "RANDOM_ID"
+ },
+ "isEnable": {
+ "description": "是否启用",
+ "type": "boolean",
+ "format": "boolean",
+ "example": true
+ },
+ "updateTime": {
+ "description": "最后更新时间",
+ "type": "string"
+ },
+ "url": {
+ "description": "目标链接",
+ "type": "string",
+ "format": "string",
+ "example": "https://github.com/jwma/jump-jump"
+ }
+ }
+ },
+ "ShortLinkDataAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "histories": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/RequestHistory"
+ }
+ }
+ }
+ },
+ "ShortLinkNotFoundConfig": {
+ "type": "object",
+ "required": [
+ "mode",
+ "value"
+ ],
+ "properties": {
+ "mode": {
+ "description": "模式",
+ "type": "string",
+ "enum": [
+ "content",
+ "redirect"
+ ],
+ "example": "content"
+ },
+ "value": {
+ "description": "值",
+ "type": "string",
+ "example": "page not found"
+ }
+ }
+ },
+ "SystemConfig": {
+ "type": "object",
+ "properties": {
+ "idConfig": {
+ "description": "ID 配置",
+ "$ref": "#/definitions/IdConfig"
+ },
+ "landingHosts": {
+ "description": "落地页 Host 列表",
+ "type": "array",
+ "format": "array",
+ "items": {
+ "type": "string"
+ },
+ "example": [
+ "https://a.com/",
+ "https://b.com/"
+ ]
+ },
+ "shortLinkNotFoundConfig": {
+ "description": "短链接 404 配置",
+ "$ref": "#/definitions/ShortLinkNotFoundConfig"
+ }
+ }
+ },
+ "UpdateLandingHostsAPIRequest": {
+ "type": "object",
+ "properties": {
+ "hosts": {
+ "type": "array",
+ "format": "array",
+ "items": {
+ "type": "string"
+ },
+ "example": [
+ "https://a.com/",
+ "https://b.com/"
+ ]
+ }
+ }
+ },
+ "UpdateShortLinkAPIRequest": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "description": {
+ "description": "描述",
+ "type": "string",
+ "example": "Jump Jump project"
+ },
+ "isEnable": {
+ "description": "是否启用",
+ "type": "boolean",
+ "format": "boolean",
+ "example": true
+ },
+ "url": {
+ "description": "目标链接",
+ "type": "string",
+ "example": "https://github.com/jwma/jump-jump"
+ }
+ }
+ },
+ "UpdateShortLinkAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "shortLink": {
+ "$ref": "#/definitions/ShortLinkData"
+ }
+ }
+ }
+ },
+ "securityDefinitions": {
+ "ApiKeyAuth": {
+ "type": "apiKey",
+ "name": "Authorization",
+ "in": "header"
+ }
+ }
+}`
+
+type swaggerInfo struct {
+ Version string
+ Host string
+ BasePath string
+ Schemes []string
+ Title string
+ Description string
+}
+
+// SwaggerInfo holds exported Swagger Info so clients can modify it
+var SwaggerInfo = swaggerInfo{
+ Version: "",
+ Host: "",
+ BasePath: "",
+ Schemes: []string{},
+ Title: "",
+ Description: "",
+}
+
+type s struct{}
+
+func (s *s) ReadDoc() string {
+ sInfo := SwaggerInfo
+ sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1)
+
+ t, err := template.New("swagger_info").Funcs(template.FuncMap{
+ "marshal": func(v interface{}) string {
+ a, _ := json.Marshal(v)
+ return string(a)
+ },
+ }).Parse(doc)
+ if err != nil {
+ return doc
+ }
+
+ var tpl bytes.Buffer
+ if err := t.Execute(&tpl, sInfo); err != nil {
+ return doc
+ }
+
+ return tpl.String()
+}
+
+func init() {
+ swag.Register(swag.Name, &s{})
+}
diff --git a/docs/swagger.json b/docs/swagger.json
new file mode 100644
index 0000000..395d7fe
--- /dev/null
+++ b/docs/swagger.json
@@ -0,0 +1,1062 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "contact": {
+ "name": "MJ Ma",
+ "url": "https://www.linkedin.com/in/mj-profile/",
+ "email": "m.mjw.ma@gmail.com"
+ },
+ "license": {
+ "name": "MIT",
+ "url": "https://github.com/jwma/jump-jump/blob/master/LICENSE"
+ }
+ },
+ "paths": {
+ "/config": {
+ "get": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "获取系统配置信息",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "系统配置"
+ ],
+ "summary": "获取系统配置信息",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/GetConfigAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/config/id-length": {
+ "patch": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "更新短链接 ID 设置",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "系统配置"
+ ],
+ "summary": "更新短链接 ID 设置",
+ "parameters": [
+ {
+ "description": "更新短链接 ID 设置请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/IdConfig"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/GetConfigAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/config/landing-hosts": {
+ "patch": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "更新落地页 Hosts",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "系统配置"
+ ],
+ "summary": "更新落地页 Hosts",
+ "parameters": [
+ {
+ "description": "更新落地页 Hosts 请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/UpdateLandingHostsAPIRequest"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/GetConfigAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/config/short-link-404-handling": {
+ "patch": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "更新短链接 404 设置",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "系统配置"
+ ],
+ "summary": "更新短链接 404 设置",
+ "parameters": [
+ {
+ "description": "更新短链接 404 设置请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/ShortLinkNotFoundConfig"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/GetConfigAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/short-link/": {
+ "get": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "短链接列表",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "短链接"
+ ],
+ "summary": "短链接列表",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "页码",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "每页条数",
+ "name": "pageSize",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/ListShortLinksAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ },
+ "post": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "创建短链接",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "短链接"
+ ],
+ "summary": "创建短链接",
+ "parameters": [
+ {
+ "description": "创建短链接请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateShortLinkAPIRequest"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/CreateShortLinkAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/short-link/{id}": {
+ "get": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "获取系统配置信息",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "短链接"
+ ],
+ "summary": "获取指定 ID 短链接",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "短链接 ID",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/GetShortLinkAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ },
+ "delete": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "删除短链接",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "短链接"
+ ],
+ "summary": "删除短链接",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "短链接 ID",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/Response"
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ },
+ "patch": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "更新短链接",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "短链接"
+ ],
+ "summary": "更新短链接",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "短链接 ID",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "description": "更新短链接请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/UpdateShortLinkAPIRequest"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/UpdateShortLinkAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/short-link/{id}/data": {
+ "get": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "可查询短链接某个日期范围内的访问数据",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "短链接"
+ ],
+ "summary": "短链接访问数据",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "短链接 ID",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "开始日期 YYYY-mm-dd",
+ "name": "startDate",
+ "in": "query",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "结束日期 YYYY-mm-dd",
+ "name": "endDate",
+ "in": "query",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/ShortLinkDataAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/user/change-password": {
+ "post": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "修改账号密码",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "账号"
+ ],
+ "summary": "修改账号密码",
+ "parameters": [
+ {
+ "description": "修改密码请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/ChangePasswordAPIRequest"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/Response"
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/user/info": {
+ "get": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "获取账号信息",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "账号"
+ ],
+ "summary": "获取账号信息",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/GetUserInfoAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ },
+ "/user/login": {
+ "post": {
+ "description": "账号密码登入",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "账号"
+ ],
+ "summary": "账号登入",
+ "parameters": [
+ {
+ "description": "登入请求",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/LoginAPIRequest"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/Response"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/LoginAPIResponseData"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "/user/logout": {
+ "post": {
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
+ "description": "登出",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "账号"
+ ],
+ "summary": "登出",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/Response"
+ }
+ },
+ "401": {
+ "description": ""
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "ChangePasswordAPIRequest": {
+ "type": "object",
+ "properties": {
+ "newPassword": {
+ "description": "新密码",
+ "type": "string"
+ },
+ "password": {
+ "description": "原密码",
+ "type": "string"
+ }
+ }
+ },
+ "CreateShortLinkAPIRequest": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "description": "描述",
+ "type": "string",
+ "example": "Jump Jump project"
+ },
+ "id": {
+ "description": "只有管理员可以在创建的时候指定 ID",
+ "type": "string",
+ "format": "string",
+ "example": "RANDOM_ID"
+ },
+ "idLength": {
+ "description": "短链接 ID 长度",
+ "type": "integer",
+ "format": "int",
+ "example": 4
+ },
+ "isEnable": {
+ "description": "是否启用",
+ "type": "boolean",
+ "format": "boolean",
+ "example": true
+ },
+ "url": {
+ "description": "目标链接",
+ "type": "string",
+ "example": "https://github.com/jwma/jump-jump"
+ }
+ }
+ },
+ "CreateShortLinkAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "shortLink": {
+ "$ref": "#/definitions/ShortLinkData"
+ }
+ }
+ },
+ "GetConfigAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "config": {
+ "$ref": "#/definitions/SystemConfig"
+ }
+ }
+ },
+ "GetShortLinkAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "shortLink": {
+ "$ref": "#/definitions/ShortLinkData"
+ }
+ }
+ },
+ "GetUserInfoAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "role": {
+ "description": "角色,1 普通用户 | 2 管理员",
+ "type": "integer",
+ "enum": [
+ 1,
+ 2
+ ],
+ "example": 1
+ },
+ "username": {
+ "description": "用户名",
+ "type": "string",
+ "example": "admin"
+ }
+ }
+ },
+ "IdConfig": {
+ "type": "object",
+ "properties": {
+ "idLength": {
+ "description": "ID 长度",
+ "type": "integer",
+ "format": "int",
+ "example": 6
+ },
+ "idMaximumLength": {
+ "description": "最大 ID 长度",
+ "type": "integer",
+ "format": "int",
+ "example": 10
+ },
+ "idMinimumLength": {
+ "description": "最小 ID 长度",
+ "type": "integer",
+ "format": "int",
+ "example": 2
+ }
+ }
+ },
+ "ListShortLinksAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "shortLinks": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/ShortLinkData"
+ }
+ },
+ "total": {
+ "type": "integer",
+ "format": "10",
+ "example": 10
+ }
+ }
+ },
+ "LoginAPIRequest": {
+ "type": "object",
+ "required": [
+ "password",
+ "username"
+ ],
+ "properties": {
+ "password": {
+ "description": "密码",
+ "type": "string",
+ "example": "your_password"
+ },
+ "username": {
+ "description": "用户名",
+ "type": "string",
+ "example": "your_username"
+ }
+ }
+ },
+ "LoginAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "token": {
+ "description": "json web token",
+ "type": "string",
+ "example": "xxx.xxx.xxx"
+ }
+ }
+ },
+ "RequestHistory": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "ip": {
+ "type": "string"
+ },
+ "time": {
+ "type": "string"
+ },
+ "ua": {
+ "type": "string"
+ },
+ "url": {
+ "description": "由于短链接的目标连接可能会被修改,可以在访问历史记录中记录一下当前的目标连接",
+ "type": "string"
+ }
+ }
+ },
+ "Response": {
+ "type": "object",
+ "properties": {
+ "code": {
+ "type": "integer",
+ "format": "int",
+ "default": 0,
+ "example": 0
+ },
+ "data": {
+ "type": "object"
+ },
+ "msg": {
+ "type": "string",
+ "default": "ok",
+ "example": "ok"
+ }
+ }
+ },
+ "ShortLinkData": {
+ "type": "object",
+ "properties": {
+ "createTime": {
+ "description": "创建时间",
+ "type": "string"
+ },
+ "createdBy": {
+ "description": "创建者",
+ "type": "string",
+ "format": "string",
+ "example": "admin"
+ },
+ "description": {
+ "description": "描述",
+ "type": "string",
+ "format": "string",
+ "example": "Jump Jump project"
+ },
+ "id": {
+ "type": "string",
+ "format": "string",
+ "example": "RANDOM_ID"
+ },
+ "isEnable": {
+ "description": "是否启用",
+ "type": "boolean",
+ "format": "boolean",
+ "example": true
+ },
+ "updateTime": {
+ "description": "最后更新时间",
+ "type": "string"
+ },
+ "url": {
+ "description": "目标链接",
+ "type": "string",
+ "format": "string",
+ "example": "https://github.com/jwma/jump-jump"
+ }
+ }
+ },
+ "ShortLinkDataAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "histories": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/RequestHistory"
+ }
+ }
+ }
+ },
+ "ShortLinkNotFoundConfig": {
+ "type": "object",
+ "required": [
+ "mode",
+ "value"
+ ],
+ "properties": {
+ "mode": {
+ "description": "模式",
+ "type": "string",
+ "enum": [
+ "content",
+ "redirect"
+ ],
+ "example": "content"
+ },
+ "value": {
+ "description": "值",
+ "type": "string",
+ "example": "page not found"
+ }
+ }
+ },
+ "SystemConfig": {
+ "type": "object",
+ "properties": {
+ "idConfig": {
+ "description": "ID 配置",
+ "$ref": "#/definitions/IdConfig"
+ },
+ "landingHosts": {
+ "description": "落地页 Host 列表",
+ "type": "array",
+ "format": "array",
+ "items": {
+ "type": "string"
+ },
+ "example": [
+ "https://a.com/",
+ "https://b.com/"
+ ]
+ },
+ "shortLinkNotFoundConfig": {
+ "description": "短链接 404 配置",
+ "$ref": "#/definitions/ShortLinkNotFoundConfig"
+ }
+ }
+ },
+ "UpdateLandingHostsAPIRequest": {
+ "type": "object",
+ "properties": {
+ "hosts": {
+ "type": "array",
+ "format": "array",
+ "items": {
+ "type": "string"
+ },
+ "example": [
+ "https://a.com/",
+ "https://b.com/"
+ ]
+ }
+ }
+ },
+ "UpdateShortLinkAPIRequest": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "description": {
+ "description": "描述",
+ "type": "string",
+ "example": "Jump Jump project"
+ },
+ "isEnable": {
+ "description": "是否启用",
+ "type": "boolean",
+ "format": "boolean",
+ "example": true
+ },
+ "url": {
+ "description": "目标链接",
+ "type": "string",
+ "example": "https://github.com/jwma/jump-jump"
+ }
+ }
+ },
+ "UpdateShortLinkAPIResponseData": {
+ "type": "object",
+ "properties": {
+ "shortLink": {
+ "$ref": "#/definitions/ShortLinkData"
+ }
+ }
+ }
+ },
+ "securityDefinitions": {
+ "ApiKeyAuth": {
+ "type": "apiKey",
+ "name": "Authorization",
+ "in": "header"
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
new file mode 100644
index 0000000..882bbfa
--- /dev/null
+++ b/docs/swagger.yaml
@@ -0,0 +1,672 @@
+definitions:
+ ChangePasswordAPIRequest:
+ properties:
+ newPassword:
+ description: 新密码
+ type: string
+ password:
+ description: 原密码
+ type: string
+ type: object
+ CreateShortLinkAPIRequest:
+ properties:
+ description:
+ description: 描述
+ example: Jump Jump project
+ type: string
+ id:
+ description: 只有管理员可以在创建的时候指定 ID
+ example: RANDOM_ID
+ format: string
+ type: string
+ idLength:
+ description: 短链接 ID 长度
+ example: 4
+ format: int
+ type: integer
+ isEnable:
+ description: 是否启用
+ example: true
+ format: boolean
+ type: boolean
+ url:
+ description: 目标链接
+ example: https://github.com/jwma/jump-jump
+ type: string
+ type: object
+ CreateShortLinkAPIResponseData:
+ properties:
+ shortLink:
+ $ref: '#/definitions/ShortLinkData'
+ type: object
+ GetConfigAPIResponseData:
+ properties:
+ config:
+ $ref: '#/definitions/SystemConfig'
+ type: object
+ GetShortLinkAPIResponseData:
+ properties:
+ shortLink:
+ $ref: '#/definitions/ShortLinkData'
+ type: object
+ GetUserInfoAPIResponseData:
+ properties:
+ role:
+ description: 角色,1 普通用户 | 2 管理员
+ enum:
+ - 1
+ - 2
+ example: 1
+ type: integer
+ username:
+ description: 用户名
+ example: admin
+ type: string
+ type: object
+ IdConfig:
+ properties:
+ idLength:
+ description: ID 长度
+ example: 6
+ format: int
+ type: integer
+ idMaximumLength:
+ description: 最大 ID 长度
+ example: 10
+ format: int
+ type: integer
+ idMinimumLength:
+ description: 最小 ID 长度
+ example: 2
+ format: int
+ type: integer
+ type: object
+ ListShortLinksAPIResponseData:
+ properties:
+ shortLinks:
+ items:
+ $ref: '#/definitions/ShortLinkData'
+ type: array
+ total:
+ example: 10
+ format: "10"
+ type: integer
+ type: object
+ LoginAPIRequest:
+ properties:
+ password:
+ description: 密码
+ example: your_password
+ type: string
+ username:
+ description: 用户名
+ example: your_username
+ type: string
+ required:
+ - password
+ - username
+ type: object
+ LoginAPIResponseData:
+ properties:
+ token:
+ description: json web token
+ example: xxx.xxx.xxx
+ type: string
+ type: object
+ RequestHistory:
+ properties:
+ id:
+ type: string
+ ip:
+ type: string
+ time:
+ type: string
+ ua:
+ type: string
+ url:
+ description: 由于短链接的目标连接可能会被修改,可以在访问历史记录中记录一下当前的目标连接
+ type: string
+ type: object
+ Response:
+ properties:
+ code:
+ default: 0
+ example: 0
+ format: int
+ type: integer
+ data:
+ type: object
+ msg:
+ default: ok
+ example: ok
+ type: string
+ type: object
+ ShortLinkData:
+ properties:
+ createTime:
+ description: 创建时间
+ type: string
+ createdBy:
+ description: 创建者
+ example: admin
+ format: string
+ type: string
+ description:
+ description: 描述
+ example: Jump Jump project
+ format: string
+ type: string
+ id:
+ example: RANDOM_ID
+ format: string
+ type: string
+ isEnable:
+ description: 是否启用
+ example: true
+ format: boolean
+ type: boolean
+ updateTime:
+ description: 最后更新时间
+ type: string
+ url:
+ description: 目标链接
+ example: https://github.com/jwma/jump-jump
+ format: string
+ type: string
+ type: object
+ ShortLinkDataAPIResponseData:
+ properties:
+ histories:
+ items:
+ $ref: '#/definitions/RequestHistory'
+ type: array
+ type: object
+ ShortLinkNotFoundConfig:
+ properties:
+ mode:
+ description: 模式
+ enum:
+ - content
+ - redirect
+ example: content
+ type: string
+ value:
+ description: 值
+ example: page not found
+ type: string
+ required:
+ - mode
+ - value
+ type: object
+ SystemConfig:
+ properties:
+ idConfig:
+ $ref: '#/definitions/IdConfig'
+ description: ID 配置
+ landingHosts:
+ description: 落地页 Host 列表
+ example:
+ - https://a.com/
+ - https://b.com/
+ format: array
+ items:
+ type: string
+ type: array
+ shortLinkNotFoundConfig:
+ $ref: '#/definitions/ShortLinkNotFoundConfig'
+ description: 短链接 404 配置
+ type: object
+ UpdateLandingHostsAPIRequest:
+ properties:
+ hosts:
+ example:
+ - https://a.com/
+ - https://b.com/
+ format: array
+ items:
+ type: string
+ type: array
+ type: object
+ UpdateShortLinkAPIRequest:
+ properties:
+ description:
+ description: 描述
+ example: Jump Jump project
+ type: string
+ isEnable:
+ description: 是否启用
+ example: true
+ format: boolean
+ type: boolean
+ url:
+ description: 目标链接
+ example: https://github.com/jwma/jump-jump
+ type: string
+ required:
+ - url
+ type: object
+ UpdateShortLinkAPIResponseData:
+ properties:
+ shortLink:
+ $ref: '#/definitions/ShortLinkData'
+ type: object
+info:
+ contact:
+ email: m.mjw.ma@gmail.com
+ name: MJ Ma
+ url: https://www.linkedin.com/in/mj-profile/
+ license:
+ name: MIT
+ url: https://github.com/jwma/jump-jump/blob/master/LICENSE
+paths:
+ /config:
+ get:
+ consumes:
+ - application/json
+ description: 获取系统配置信息
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ allOf:
+ - $ref: '#/definitions/Response'
+ - properties:
+ data:
+ $ref: '#/definitions/GetConfigAPIResponseData'
+ type: object
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 获取系统配置信息
+ tags:
+ - 系统配置
+ /config/id-length:
+ patch:
+ consumes:
+ - application/json
+ description: 更新短链接 ID 设置
+ parameters:
+ - description: 更新短链接 ID 设置请求
+ in: body
+ name: body
+ required: true
+ schema:
+ $ref: '#/definitions/IdConfig'
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ allOf:
+ - $ref: '#/definitions/Response'
+ - properties:
+ data:
+ $ref: '#/definitions/GetConfigAPIResponseData'
+ type: object
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 更新短链接 ID 设置
+ tags:
+ - 系统配置
+ /config/landing-hosts:
+ patch:
+ consumes:
+ - application/json
+ description: 更新落地页 Hosts
+ parameters:
+ - description: 更新落地页 Hosts 请求
+ in: body
+ name: body
+ required: true
+ schema:
+ $ref: '#/definitions/UpdateLandingHostsAPIRequest'
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ allOf:
+ - $ref: '#/definitions/Response'
+ - properties:
+ data:
+ $ref: '#/definitions/GetConfigAPIResponseData'
+ type: object
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 更新落地页 Hosts
+ tags:
+ - 系统配置
+ /config/short-link-404-handling:
+ patch:
+ consumes:
+ - application/json
+ description: 更新短链接 404 设置
+ parameters:
+ - description: 更新短链接 404 设置请求
+ in: body
+ name: body
+ required: true
+ schema:
+ $ref: '#/definitions/ShortLinkNotFoundConfig'
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ allOf:
+ - $ref: '#/definitions/Response'
+ - properties:
+ data:
+ $ref: '#/definitions/GetConfigAPIResponseData'
+ type: object
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 更新短链接 404 设置
+ tags:
+ - 系统配置
+ /short-link/:
+ get:
+ consumes:
+ - application/json
+ description: 短链接列表
+ parameters:
+ - description: 页码
+ in: query
+ name: page
+ type: integer
+ - description: 每页条数
+ in: query
+ name: pageSize
+ type: integer
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ allOf:
+ - $ref: '#/definitions/Response'
+ - properties:
+ data:
+ $ref: '#/definitions/ListShortLinksAPIResponseData'
+ type: object
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 短链接列表
+ tags:
+ - 短链接
+ post:
+ consumes:
+ - application/json
+ description: 创建短链接
+ parameters:
+ - description: 创建短链接请求
+ in: body
+ name: body
+ required: true
+ schema:
+ $ref: '#/definitions/CreateShortLinkAPIRequest'
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ allOf:
+ - $ref: '#/definitions/Response'
+ - properties:
+ data:
+ $ref: '#/definitions/CreateShortLinkAPIResponseData'
+ type: object
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 创建短链接
+ tags:
+ - 短链接
+ /short-link/{id}:
+ delete:
+ consumes:
+ - application/json
+ description: 删除短链接
+ parameters:
+ - description: 短链接 ID
+ in: path
+ name: id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/Response'
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 删除短链接
+ tags:
+ - 短链接
+ get:
+ consumes:
+ - application/json
+ description: 获取系统配置信息
+ parameters:
+ - description: 短链接 ID
+ in: path
+ name: id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ allOf:
+ - $ref: '#/definitions/Response'
+ - properties:
+ data:
+ $ref: '#/definitions/GetShortLinkAPIResponseData'
+ type: object
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 获取指定 ID 短链接
+ tags:
+ - 短链接
+ patch:
+ consumes:
+ - application/json
+ description: 更新短链接
+ parameters:
+ - description: 短链接 ID
+ in: path
+ name: id
+ required: true
+ type: string
+ - description: 更新短链接请求
+ in: body
+ name: body
+ required: true
+ schema:
+ $ref: '#/definitions/UpdateShortLinkAPIRequest'
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ allOf:
+ - $ref: '#/definitions/Response'
+ - properties:
+ data:
+ $ref: '#/definitions/UpdateShortLinkAPIResponseData'
+ type: object
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 更新短链接
+ tags:
+ - 短链接
+ /short-link/{id}/data:
+ get:
+ consumes:
+ - application/json
+ description: 可查询短链接某个日期范围内的访问数据
+ parameters:
+ - description: 短链接 ID
+ in: path
+ name: id
+ required: true
+ type: string
+ - description: 开始日期 YYYY-mm-dd
+ in: query
+ name: startDate
+ required: true
+ type: string
+ - description: 结束日期 YYYY-mm-dd
+ in: query
+ name: endDate
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ allOf:
+ - $ref: '#/definitions/Response'
+ - properties:
+ data:
+ $ref: '#/definitions/ShortLinkDataAPIResponseData'
+ type: object
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 短链接访问数据
+ tags:
+ - 短链接
+ /user/change-password:
+ post:
+ consumes:
+ - application/json
+ description: 修改账号密码
+ parameters:
+ - description: 修改密码请求
+ in: body
+ name: body
+ required: true
+ schema:
+ $ref: '#/definitions/ChangePasswordAPIRequest'
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/Response'
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 修改账号密码
+ tags:
+ - 账号
+ /user/info:
+ get:
+ consumes:
+ - application/json
+ description: 获取账号信息
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ allOf:
+ - $ref: '#/definitions/Response'
+ - properties:
+ data:
+ $ref: '#/definitions/GetUserInfoAPIResponseData'
+ type: object
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 获取账号信息
+ tags:
+ - 账号
+ /user/login:
+ post:
+ consumes:
+ - application/json
+ description: 账号密码登入
+ parameters:
+ - description: 登入请求
+ in: body
+ name: body
+ required: true
+ schema:
+ $ref: '#/definitions/LoginAPIRequest'
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ allOf:
+ - $ref: '#/definitions/Response'
+ - properties:
+ data:
+ $ref: '#/definitions/LoginAPIResponseData'
+ type: object
+ summary: 账号登入
+ tags:
+ - 账号
+ /user/logout:
+ post:
+ consumes:
+ - application/json
+ description: 登出
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/Response'
+ "401":
+ description: ""
+ security:
+ - ApiKeyAuth: []
+ summary: 登出
+ tags:
+ - 账号
+securityDefinitions:
+ ApiKeyAuth:
+ in: header
+ name: Authorization
+ type: apiKey
+swagger: "2.0"
diff --git a/go.mod b/go.mod
index a1fb12b..d79438e 100644
--- a/go.mod
+++ b/go.mod
@@ -3,26 +3,29 @@ module github.com/jwma/jump-jump
go 1.13
require (
+ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/gin-contrib/cors v1.3.1
- github.com/gin-gonic/gin v1.5.0
- github.com/go-playground/universal-translator v0.17.0 // indirect
+ github.com/gin-gonic/gin v1.6.3
+ github.com/go-openapi/spec v0.20.3 // indirect
+ github.com/go-playground/validator/v10 v10.4.1 // indirect
github.com/go-redis/redis v6.15.7+incompatible
- github.com/golang/protobuf v1.3.3 // indirect
- github.com/json-iterator/go v1.1.9 // indirect
+ github.com/golang/protobuf v1.4.3 // indirect
+ github.com/json-iterator/go v1.1.10 // indirect
github.com/jwma/reborn v0.0.0-20200326132007-2fa07c258aec
- github.com/leodido/go-urn v1.2.0 // indirect
- github.com/mattn/go-isatty v0.0.12 // indirect
- github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
- github.com/modern-go/reflect2 v1.0.1 // indirect
+ github.com/leodido/go-urn v1.2.1 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
github.com/mssola/user_agent v0.5.2
github.com/onsi/ginkgo v1.12.0 // indirect
github.com/onsi/gomega v1.9.0 // indirect
+ github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14
+ github.com/swaggo/gin-swagger v1.3.0
+ github.com/swaggo/swag v1.7.0
github.com/thoas/go-funk v0.6.0
- golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d
- golang.org/x/net v0.0.0-20190620200207-3b0461eec859 // indirect
- golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c // indirect
- golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 // indirect
- gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
- gopkg.in/yaml.v2 v2.2.8 // indirect
+ github.com/ugorji/go v1.2.4 // indirect
+ golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b
+ golang.org/x/net v0.0.0-20210315170653-34ac3e1c2000 // indirect
+ golang.org/x/sys v0.0.0-20210316092937-0b90fd5c4c48 // indirect
+ golang.org/x/tools v0.1.0 // indirect
+ google.golang.org/protobuf v1.25.0 // indirect
)
diff --git a/go.sum b/go.sum
index 661d39e..e16bba1 100644
--- a/go.sum
+++ b/go.sum
@@ -1,16 +1,68 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
+github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
+github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
+github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA=
github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk=
+github.com/gin-contrib/gzip v0.0.1 h1:ezvKOL6jH+jlzdHNE4h9h8q8uMpDQjyl0NN0Jd7jozc=
+github.com/gin-contrib/gzip v0.0.1/go.mod h1:fGBJBCdt6qCZuCAOwWuFhBB4OOq9EFqlo5dEaFhhu5w=
+github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
+github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y=
+github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/gin-gonic/gin v1.5.0 h1:fi+bqFAx/oLK54somfCtEZs9HeH1LHVoEPUgARpTqyc=
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
+github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
+github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
+github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
+github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
+github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
+github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
+github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
+github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg=
+github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
+github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
+github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
+github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
+github.com/go-openapi/spec v0.19.14 h1:r4fbYFo6N4ZelmSX8G6p+cv/hZRXzcuqQIADGT1iNKM=
+github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeEip0M63doA=
+github.com/go-openapi/spec v0.20.3 h1:uH9RQ6vdyPSs2pSy9fL8QPspDF2AMIMPtmK5coSSjtQ=
+github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
+github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
+github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.19.11 h1:RFTu/dlFySpyVvJDfp/7674JY4SDglYWKztbiIGFpmc=
+github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY=
+github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
+github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
+github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
@@ -19,20 +71,47 @@ github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rm
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
+github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
+github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
+github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-redis/redis v6.15.7+incompatible h1:3skhDh95XQMpnqeqNftPkQD9jL9e5e36z/1SUm6dy1U=
github.com/go-redis/redis v6.15.7+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jwma/reborn v0.0.0-20200326132007-2fa07c258aec h1:bfzlqMldSDAEG6ZDo7Y3iOu1H216vUIAcZjz2eH+kOY=
github.com/jwma/reborn v0.0.0-20200326132007-2fa07c258aec/go.mod h1:tshy8uF9ZnJaltJqDX9F/hSe6AeCf8CKbt6OO/rwxHE=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
@@ -40,10 +119,24 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
+github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
+github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
+github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
@@ -58,64 +151,183 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mssola/user_agent v0.5.2 h1:CZkTUahjL1+OcZ5zv3kZr8QiJ8jy2H08vZIEkBeRbxo=
github.com/mssola/user_agent v0.5.2/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg=
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 h1:PyYN9JH5jY9j6av01SpfRMb+1DWg/i3MbGOKPxJ2wjM=
+github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E=
+github.com/swaggo/gin-swagger v1.3.0 h1:eOmp7r57oUgZPw2dJOjcGNMse9cvXcI4tTqBcnZtPsI=
+github.com/swaggo/gin-swagger v1.3.0/go.mod h1:oy1BRA6WvgtCp848lhxce7BnWH4C8Bxa0m5SkWx+cS0=
+github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y=
+github.com/swaggo/swag v1.7.0 h1:5bCA/MTLQoIqDXXyHfOpMeDvL9j68OY/udlK4pQoo4E=
+github.com/swaggo/swag v1.7.0/go.mod h1:BdPIL73gvS9NBsdi7M1JOxLvlbfvNRaBP8m6WT6Aajo=
github.com/thoas/go-funk v0.6.0 h1:ryxN0pa9FnI7YHgODdLIZ4T6paCZJt8od6N9oRztMxM=
github.com/thoas/go-funk v0.6.0/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
+github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go v1.1.13/go.mod h1:jxau1n+/wyTGLQoCkjok9r5zFa/FxT6eI5HiHKQszjc=
+github.com/ugorji/go v1.2.4 h1:cTciPbZ/VSOzCLKclmssnfQ/jyoVyOcJ3aoJyUV1Urc=
+github.com/ugorji/go v1.2.4/go.mod h1:EuaSCk8iZMdIspsu6HXH7X2UGKw1ezO4wCfGszGmmo4=
+github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU=
+github.com/ugorji/go/codec v1.2.4 h1:C5VurWRRCKjuENsbM6GYVw8W++WVW9rSxoACKIvxzz8=
+github.com/ugorji/go/codec v1.2.4/go.mod h1:bWBu1+kIRWcF8uMklKaJrR6fTWQOwAlrIzX22pHwryA=
+github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
+github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=
-golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b h1:wSOdpTq0/eI46Ez/LkDwIsAKA71YP2SRKBODiRWM0as=
+golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210315170653-34ac3e1c2000 h1:6mqyFav9MzRNys8OnKlbKYSJxsoVvhb773Si3bu5fYE=
+golang.org/x/net v0.0.0-20210315170653-34ac3e1c2000/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c h1:jceGD5YNJGgGMkJz79agzOln1K9TaZUjv5ird16qniQ=
-golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210316092937-0b90fd5c4c48 h1:70qalHWW1n9yoI8B8zEQxFJO/D6NUWIX8SNmJO+rvNw=
+golang.org/x/sys v0.0.0-20210316092937-0b90fd5c4c48/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
+golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e h1:t96dS3DO8DGjawSLJL/HIdz8CycAd2v07XxqB3UPTi0=
+golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
+golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
+gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
-gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M=
-gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/internal/app/config/config.go b/internal/app/config/config.go
index ce1df39..fda32f8 100644
--- a/internal/app/config/config.go
+++ b/internal/app/config/config.go
@@ -13,6 +13,51 @@ const (
ShortLinkNotFoundRedirectMode = "redirect"
)
+type IdConfig struct {
+ // ID 长度
+ IdLength int `json:"idLength" format:"int" example:"6"`
+
+ // 最小 ID 长度
+ IdMinimumLength int `json:"idMinimumLength" format:"int" example:"2"`
+
+ // 最大 ID 长度
+ IdMaximumLength int `json:"idMaximumLength" format:"int" example:"10"`
+} // @name IdConfig
+
+type ShortLinkNotFoundConfig struct {
+ // 模式
+ Mode string `json:"mode" binding:"required" example:"content" enums:"content,redirect"`
+
+ // 值
+ Value string `json:"value" binding:"required" example:"page not found"`
+} // @name ShortLinkNotFoundConfig
+
+func (s *ShortLinkNotFoundConfig) ToMap() map[string]string {
+ return map[string]string{
+ "mode": s.Mode,
+ "value": s.Value,
+ }
+}
+
+type SystemConfig struct {
+ // 落地页 Host 列表
+ LandingHosts []string `json:"landingHosts" format:"array" example:"https://a.com/,https://b.com/"`
+
+ // ID 配置
+ IdConfig *IdConfig `json:"idConfig"`
+
+ // 短链接 404 配置
+ ShortLinkNotFoundConfig *ShortLinkNotFoundConfig `json:"shortLinkNotFoundConfig"`
+} // @name SystemConfig
+
+func GetIdConfig() *IdConfig {
+ return &IdConfig{
+ IdLength: config.GetIntValue("idLength", 6),
+ IdMinimumLength: config.GetIntValue("idMinimumLength", 2),
+ IdMaximumLength: config.GetIntValue("idMaximumLength", 10),
+ }
+}
+
func GetDefaultShortLinkNotFoundConfig() map[string]string {
return map[string]string{
"mode": ShortLinkNotFoundContentMode,
@@ -20,13 +65,40 @@ func GetDefaultShortLinkNotFoundConfig() map[string]string {
}
}
-func NewShortLinkNotFoundConfig(mode string, value string) map[string]string {
- return map[string]string{
- "mode": mode,
- "value": value,
+func GetShortLinkNotFoundConfig() *ShortLinkNotFoundConfig {
+ c := config.GetStringStringMapValue("shortLinkNotFoundConfig", GetDefaultShortLinkNotFoundConfig())
+
+ return &ShortLinkNotFoundConfig{
+ Mode: c["mode"],
+ Value: c["value"],
+ }
+}
+
+func GetSystemConfig() *SystemConfig {
+ return &SystemConfig{
+ LandingHosts: config.GetStringSliceValue("landingHosts", make([]string, 0)),
+ IdConfig: GetIdConfig(),
+ ShortLinkNotFoundConfig: GetShortLinkNotFoundConfig(),
}
}
+func UpdateLandingHosts(hosts []string) {
+ config.SetValue("landingHosts", hosts)
+ config.Persist()
+}
+
+func UpdateIdConfig(c *IdConfig) {
+ config.SetValue("idMinimumLength", c.IdMinimumLength)
+ config.SetValue("idLength", c.IdLength)
+ config.SetValue("idMaximumLength", c.IdMaximumLength)
+ config.Persist()
+}
+
+func UpdateShortLinkNotFoundConfig(s *ShortLinkNotFoundConfig) {
+ config.SetValue("shortLinkNotFoundConfig", s.ToMap())
+ config.Persist()
+}
+
func getDefaultConfig() *reborn.Config {
d := reborn.NewConfig()
d.SetValue("landingHosts", []string{"http://127.0.0.1:8081/"})
diff --git a/internal/app/handlers/config.go b/internal/app/handlers/config.go
index b131928..a399b8e 100644
--- a/internal/app/handlers/config.go
+++ b/internal/app/handlers/config.go
@@ -8,181 +8,115 @@ import (
"net/http"
)
-func GetConfig(c *gin.Context) {
- cfg := config.GetConfig()
- landingHosts := cfg.GetStringSliceValue("landingHosts", make([]string, 0))
- idMinimumLength := cfg.GetIntValue("idMinimumLength", 2)
- idLength := cfg.GetIntValue("idLength", 6)
- idMaximumLength := cfg.GetIntValue("idMaximumLength", 10)
- shortLinkNotFoundConfig := cfg.GetStringStringMapValue("shortLinkNotFoundConfig",
- config.GetDefaultShortLinkNotFoundConfig())
-
- c.JSON(http.StatusOK, gin.H{
- "msg": "ok",
- "code": 0,
- "data": gin.H{
- "config": gin.H{
- "landingHosts": landingHosts,
- "idConfig": gin.H{
- "idMinimumLength": idMinimumLength,
- "idLength": idLength,
- "idMaximumLength": idMaximumLength,
- },
- "shortLinkNotFoundConfig": shortLinkNotFoundConfig,
- },
- },
- })
-}
-
-type LandingHostsParameter struct {
- Hosts []string `json:"hosts"`
+// GetConfigAPI godoc
+// @Security ApiKeyAuth
+// @Summary 获取系统配置信息
+// @Description 获取系统配置信息
+// @Tags 系统配置
+// @Accept json
+// @Produce json
+// @Success 200 {object} models.Response{data=models.GetConfigAPIResponseData}
+// @Failure 401
+// @Router /config [get]
+func GetConfigAPI(c *gin.Context) {
+ c.JSON(http.StatusOK, models.NewSuccessResponse(models.GetConfigAPIResponseData{Config: config.GetSystemConfig()}))
}
+// UpdateLandingHostsAPI godoc
+// @Security ApiKeyAuth
+// @Summary 更新落地页 Hosts
+// @Description 更新落地页 Hosts
+// @Tags 系统配置
+// @Accept json
+// @Produce json
+// @Param body body models.UpdateLandingHostsAPIRequest true "更新落地页 Hosts 请求"
+// @Success 200 {object} models.Response{data=models.GetConfigAPIResponseData}
+// @Failure 401
+// @Router /config/landing-hosts [patch]
func UpdateLandingHostsAPI() gin.HandlerFunc {
return Authenticator(func(c *gin.Context, user *models.User) {
if user.Role != models.RoleAdmin {
- c.JSON(http.StatusOK, gin.H{
- "msg": "你无权修改短链接域名",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("你无权修改短链接域名"))
return
}
- p := &LandingHostsParameter{}
+ p := &models.UpdateLandingHostsAPIRequest{}
if err := c.ShouldBindJSON(p); err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse(err.Error()))
return
}
- cfg := config.GetConfig()
- cfg.SetValue("landingHosts", p.Hosts)
- cfg.Persist()
-
- c.JSON(http.StatusOK, gin.H{
- "msg": "",
- "code": 0,
- "data": gin.H{
- "config": gin.H{"landingHosts": cfg.GetStringSliceValue("landingHosts", make([]string, 0))},
- },
- })
+ config.UpdateLandingHosts(p.Hosts) // 更新
+ c.JSON(http.StatusOK, models.NewSuccessResponse(models.GetConfigAPIResponseData{Config: config.GetSystemConfig()}))
})
}
-type idLengthParameter struct {
- IdMinimumLength int `json:"idMinimumLength"`
- IdLength int `json:"idLength"`
- IdMaximumLength int `json:"idMaximumLength"`
-}
-
+// UpdateIdLengthConfigAPI godoc
+// @Security ApiKeyAuth
+// @Summary 更新短链接 ID 设置
+// @Description 更新短链接 ID 设置
+// @Tags 系统配置
+// @Accept json
+// @Produce json
+// @Param body body config.IdConfig true "更新短链接 ID 设置请求"
+// @Success 200 {object} models.Response{data=models.GetConfigAPIResponseData}
+// @Failure 401
+// @Router /config/id-length [patch]
func UpdateIdLengthConfigAPI() gin.HandlerFunc {
return Authenticator(func(c *gin.Context, user *models.User) {
if user.Role != models.RoleAdmin {
- c.JSON(http.StatusOK, gin.H{
- "msg": "你无权修改随机 ID 长度设置",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("你无权修改随机 ID 长度设置"))
return
}
- p := &idLengthParameter{}
-
+ p := &config.IdConfig{}
if err := c.ShouldBindJSON(p); err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse(err.Error()))
return
}
if p.IdMinimumLength <= p.IdLength && p.IdLength <= p.IdMaximumLength &&
p.IdMinimumLength > 0 && p.IdLength > 0 && p.IdMaximumLength > 0 {
- cfg := config.GetConfig()
- cfg.SetValue("idMinimumLength", p.IdMinimumLength)
- cfg.SetValue("idLength", p.IdLength)
- cfg.SetValue("idMaximumLength", p.IdMaximumLength)
- cfg.Persist()
-
- c.JSON(http.StatusOK, gin.H{
- "msg": "",
- "code": 0,
- "data": gin.H{
- "config": gin.H{
- "idConfig": gin.H{
- "idMinimumLength": p.IdMinimumLength,
- "idLength": p.IdLength,
- "idMaximumLength": p.IdMaximumLength,
- },
- },
- },
- })
+ config.UpdateIdConfig(p)
+ c.JSON(http.StatusOK, models.NewSuccessResponse(models.GetConfigAPIResponseData{Config: config.GetSystemConfig()}))
return
}
- c.JSON(http.StatusOK, gin.H{
- "msg": "最小长度 <= 默认长度 <= 最大长度,三个值均大于 0",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("最小长度 <= 默认长度 <= 最大长度,三个值均大于 0"))
})
}
-type shortLinkNotFoundConfigParameter struct {
- Mode string `json:"mode" binding:"required"`
- Value string `json:"value" binding:"required"`
-}
-
+// UpdateShortLinkNotFoundConfigAPI godoc
+// @Security ApiKeyAuth
+// @Summary 更新短链接 404 设置
+// @Description 更新短链接 404 设置
+// @Tags 系统配置
+// @Accept json
+// @Produce json
+// @Param body body config.ShortLinkNotFoundConfig true "更新短链接 404 设置请求"
+// @Success 200 {object} models.Response{data=models.GetConfigAPIResponseData}
+// @Failure 401
+// @Router /config/short-link-404-handling [patch]
func UpdateShortLinkNotFoundConfigAPI() gin.HandlerFunc {
return Authenticator(func(c *gin.Context, user *models.User) {
if user.Role != models.RoleAdmin {
- c.JSON(http.StatusOK, gin.H{
- "msg": "你无权修改短链接 404 处理配置",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("你无权修改短链接 404 处理配置"))
return
}
- p := &shortLinkNotFoundConfigParameter{}
-
+ p := &config.ShortLinkNotFoundConfig{}
if err := c.ShouldBindJSON(p); err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse(err.Error()))
return
}
if !funk.ContainsString([]string{config.ShortLinkNotFoundContentMode, config.ShortLinkNotFoundRedirectMode},
p.Mode) {
- c.JSON(http.StatusOK, gin.H{
- "msg": "处理模式参数不正确",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("处理模式参数不正确"))
return
}
- cc := config.NewShortLinkNotFoundConfig(p.Mode, p.Value)
- cfg := config.GetConfig()
- cfg.SetValue("shortLinkNotFoundConfig", cc)
- cfg.Persist()
-
- c.JSON(http.StatusOK, gin.H{
- "msg": "",
- "code": 0,
- "data": gin.H{
- "config": gin.H{
- "shortLinkNotFoundConfig": cc,
- },
- },
- })
+ config.UpdateShortLinkNotFoundConfig(p)
+ c.JSON(http.StatusOK, models.NewSuccessResponse(models.GetConfigAPIResponseData{Config: config.GetSystemConfig()}))
})
}
diff --git a/internal/app/handlers/shortlink.go b/internal/app/handlers/shortlink.go
index 66ca443..ea43b5f 100644
--- a/internal/app/handlers/shortlink.go
+++ b/internal/app/handlers/shortlink.go
@@ -13,57 +13,62 @@ import (
"time"
)
+// GetShortLinkAPI godoc
+// @Security ApiKeyAuth
+// @Summary 获取指定 ID 短链接
+// @Description 获取系统配置信息
+// @Tags 短链接
+// @Accept json
+// @Produce json
+// @Param id path string true "短链接 ID"
+// @Success 200 {object} models.Response{data=models.GetShortLinkAPIResponseData}
+// @Failure 401
+// @Router /short-link/{id} [get]
func GetShortLinkAPI() gin.HandlerFunc {
return Authenticator(func(c *gin.Context, user *models.User) {
slRepo := repository.GetShortLinkRepo(db.GetRedisClient())
s, err := slRepo.Get(c.Param("id"))
if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse(err.Error()))
return
}
if !user.IsAdmin() && user.Username != s.CreatedBy {
- c.JSON(http.StatusOK, gin.H{
- "msg": "你无权查看",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("你无权查看"))
return
}
- c.JSON(http.StatusOK, gin.H{
- "msg": "ok",
- "code": 0,
- "data": gin.H{
- "shortLink": s,
- },
- })
+ c.JSON(http.StatusOK, models.NewSuccessResponse(&models.GetShortLinkAPIResponseData{
+ ShortLinkData: models.ToShortLinkData(s),
+ }))
})
}
+// CreateShortLinkAPI godoc
+// @Security ApiKeyAuth
+// @Summary 创建短链接
+// @Description 创建短链接
+// @Tags 短链接
+// @Accept json
+// @Produce json
+// @Param body body models.CreateShortLinkAPIRequest true "创建短链接请求"
+// @Success 200 {object} models.Response{data=models.CreateShortLinkAPIResponseData}
+// @Failure 401
+// @Router /short-link/ [post]
func CreateShortLinkAPI() gin.HandlerFunc {
return Authenticator(func(c *gin.Context, user *models.User) {
var err error
- s := &models.ShortLink{CreatedBy: user.Username}
- params := &models.CreateShortLinkParameter{}
- params.ShortLink = s
+ params := &models.CreateShortLinkAPIRequest{}
if err := c.ShouldBindJSON(¶ms); err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": "参数错误",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("参数错误"))
return
}
+ s := models.NewShortLink(user.Username, params)
repo := repository.GetShortLinkRepo(db.GetRedisClient())
- cfg := config.GetConfig()
- idLen := config.GetConfig().GetIntValue("idLength", 6)
+ idCfg := config.GetIdConfig()
+ idLen := idCfg.IdLength
if user.Role == models.RoleUser {
s.Id = "" // 如果是普通用户,创建时不可以指定 ID
@@ -74,19 +79,12 @@ func CreateShortLinkAPI() gin.HandlerFunc {
checkShortLink, _ := repo.Get(s.Id)
if checkShortLink.Id != "" {
- c.JSON(http.StatusOK, gin.H{
- "msg": fmt.Sprintf("%s 已被占用,请使用其他 ID。", s.Id),
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse(fmt.Sprintf("%s 已被占用,请使用其他 ID。", s.Id)))
return
}
} else {
// 如果管理员没有指定 ID,则计算随机 ID 的长度
- idMinimumLength := cfg.GetIntValue("idMinimumLength", 2)
- idMaximumLength := cfg.GetIntValue("idMaximumLength", 10)
-
- if idMinimumLength <= params.IdLength && params.IdLength <= idMaximumLength { // 检查是否在合法的范围内
+ if idCfg.IdMinimumLength <= params.IdLength && params.IdLength <= idCfg.IdMaximumLength { // 检查是否在合法的范围内
idLen = params.IdLength
}
@@ -94,11 +92,7 @@ func CreateShortLinkAPI() gin.HandlerFunc {
if err != nil {
log.Printf("generate id failed, error: %v\n", err)
- c.JSON(http.StatusOK, gin.H{
- "msg": "服务器繁忙,请稍后再试",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("服务器繁忙,请稍后再试"))
return
}
@@ -107,113 +101,150 @@ func CreateShortLinkAPI() gin.HandlerFunc {
if s.Id == "" {
log.Println("短链接 ID 为空")
- c.JSON(http.StatusOK, gin.H{
- "msg": "ID 错误",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("ID 错误"))
}
err = repo.Save(s)
if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse(err.Error()))
return
}
- c.JSON(http.StatusOK, gin.H{
- "msg": "ok",
- "code": 0,
- "data": gin.H{"shortLink": s},
- })
+ c.JSON(http.StatusOK, models.NewSuccessResponse(models.CreateShortLinkAPIResponseData{
+ ShortLinkData: models.ToShortLinkData(s),
+ }))
})
}
+// UpdateShortLinkAPI godoc
+// @Security ApiKeyAuth
+// @Summary 更新短链接
+// @Description 更新短链接
+// @Tags 短链接
+// @Accept json
+// @Produce json
+// @Param id path string true "短链接 ID"
+// @Param body body models.UpdateShortLinkAPIRequest true "更新短链接请求"
+// @Success 200 {object} models.Response{data=models.UpdateShortLinkAPIResponseData}
+// @Failure 401
+// @Router /short-link/{id} [patch]
func UpdateShortLinkAPI() gin.HandlerFunc {
return Authenticator(func(c *gin.Context, user *models.User) {
slRepo := repository.GetShortLinkRepo(db.GetRedisClient())
s, err := slRepo.Get(c.Param("id"))
if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse(err.Error()))
return
}
if !user.IsAdmin() && user.Username != s.CreatedBy {
- c.JSON(http.StatusOK, gin.H{
- "msg": "你无权修改",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("你无权修改此短链接"))
return
}
- updateShortLink := &models.UpdateShortLinkParameter{}
+ updateShortLink := &models.UpdateShortLinkAPIRequest{}
if err := c.ShouldBindJSON(updateShortLink); err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse(err.Error()))
return
}
repo := repository.GetShortLinkRepo(db.GetRedisClient())
err = repo.Update(s, updateShortLink)
if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse(err.Error()))
+ return
}
- c.JSON(http.StatusOK, gin.H{
- "msg": "ok",
- "code": 0,
- "data": gin.H{"shortLink": s},
- })
+ c.JSON(http.StatusOK, models.NewSuccessResponse(models.UpdateShortLinkAPIResponseData{
+ ShortLinkData: models.ToShortLinkData(s),
+ }))
})
}
+// DeleteShortLinkAPI godoc
+// @Security ApiKeyAuth
+// @Summary 删除短链接
+// @Description 删除短链接
+// @Tags 短链接
+// @Accept json
+// @Produce json
+// @Param id path string true "短链接 ID"
+// @Success 200 {object} models.Response
+// @Failure 401
+// @Router /short-link/{id} [delete]
func DeleteShortLinkAPI() gin.HandlerFunc {
return Authenticator(func(c *gin.Context, user *models.User) {
slRepo := repository.GetShortLinkRepo(db.GetRedisClient())
s, err := slRepo.Get(c.Param("id"))
if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse(err.Error()))
return
}
if !user.IsAdmin() && user.Username != s.CreatedBy {
- c.JSON(http.StatusOK, gin.H{
- "msg": "你无权修改",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("你无权删除此短链接"))
return
}
repo := repository.GetShortLinkRepo(db.GetRedisClient())
repo.Delete(s)
- c.JSON(http.StatusOK, gin.H{
- "msg": "ok",
- "code": 0,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewSuccessResponse(nil))
})
}
+// ListShortLinksAPI godoc
+// @Security ApiKeyAuth
+// @Summary 短链接列表
+// @Description 短链接列表
+// @Tags 短链接
+// @Accept json
+// @Produce json
+// @Param page query int false "页码"
+// @Param pageSize query int false "每页条数"
+// @Success 200 {object} models.Response{data=models.ListShortLinksAPIResponseData}
+// @Failure 401
+// @Router /short-link/ [get]
+func ListShortLinksAPI() gin.HandlerFunc {
+ return Authenticator(func(c *gin.Context, user *models.User) {
+ var page = utils.GetIntQueryValue(c, "page", 1)
+ var pageSize = utils.GetIntQueryValue(c, "pageSize", 20)
+ start := int64((page - 1) * pageSize)
+ stop := start - 1 + int64(pageSize)
+
+ var key string
+ if user.IsAdmin() {
+ key = utils.GetShortLinksKey()
+ } else {
+ key = utils.GetUserShortLinksKey(user.Username)
+ }
+
+ slRepo := repository.GetShortLinkRepo(db.GetRedisClient())
+ result, err := slRepo.List(key, start, stop)
+ if err != nil {
+ c.JSON(http.StatusOK, models.NewErrorResponse(err.Error()))
+ return
+ }
+
+ c.JSON(http.StatusOK, models.NewSuccessResponse(&models.ListShortLinksAPIResponseData{
+ ShortLinks: models.ToShortLinkDataSlice(result.ShortLinks),
+ Total: result.Total,
+ }))
+ })
+}
+
+// ShortLinkDataAPI godoc
+// @Security ApiKeyAuth
+// @Summary 短链接访问数据
+// @Description 可查询短链接某个日期范围内的访问数据
+// @Tags 短链接
+// @Accept json
+// @Produce json
+// @Param id path string true "短链接 ID"
+// @Param startDate query string true "开始日期 YYYY-mm-dd"
+// @Param endDate query string true "结束日期 YYYY-mm-dd"
+// @Success 200 {object} models.Response{data=models.ShortLinkDataAPIResponseData}
+// @Failure 401
+// @Router /short-link/{id}/data [get]
func ShortLinkActionAPI() gin.HandlerFunc {
return Authenticator(func(c *gin.Context, user *models.User) {
@@ -222,20 +253,12 @@ func ShortLinkActionAPI() gin.HandlerFunc {
s, err := slRepo.Get(c.Param("id"))
if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse(err.Error()))
return
}
if !user.IsAdmin() && user.Username != s.CreatedBy {
- c.JSON(http.StatusOK, gin.H{
- "msg": "你无权查看",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("你无权查看"))
return
}
@@ -243,11 +266,7 @@ func ShortLinkActionAPI() gin.HandlerFunc {
endDate := c.Query("endDate")
if startDate == "" || endDate == "" {
- c.JSON(http.StatusOK, gin.H{
- "msg": "参数错误",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("参数错误"))
return
}
@@ -255,11 +274,7 @@ func ShortLinkActionAPI() gin.HandlerFunc {
endTime, err := time.ParseInLocation("2006-01-02", endDate, time.Local)
if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": "日期参数错误",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("日期参数错误"))
return
}
@@ -267,98 +282,13 @@ func ShortLinkActionAPI() gin.HandlerFunc {
rhRepo := repository.GetRequestHistoryRepo(db.GetRedisClient())
rhs := rhRepo.FindByDateRange(s.Id, startTime, endTime)
- c.JSON(http.StatusOK, gin.H{
- "msg": "ok",
- "code": 0,
- "data": gin.H{
- "histories": rhs,
- },
- })
- return
- } else if c.Param("action") == "/latest-request-history" {
- slRepo := repository.GetShortLinkRepo(db.GetRedisClient())
- s, err := slRepo.Get(c.Param("id"))
-
- if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
- return
- }
-
- if !user.IsAdmin() && user.Username != s.CreatedBy {
- c.JSON(http.StatusOK, gin.H{
- "msg": "你无权查看",
- "code": 4999,
- "data": nil,
- })
- return
- }
-
- repo := repository.GetRequestHistoryRepo(db.GetRedisClient())
- size := utils.GetIntQueryValue(c, "size", 20)
-
- r, err := repo.FindLatest(s.Id, int64(size))
-
- if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
- return
- }
-
- c.JSON(http.StatusOK, gin.H{
- "msg": "ok",
- "code": 0,
- "data": r,
- })
+ c.JSON(http.StatusOK, models.NewSuccessResponse(&models.ShortLinkDataAPIResponseData{Histories: rhs}))
return
} else if c.Param("action") == "/" {
GetShortLinkAPI()(c)
return
}
- c.JSON(http.StatusOK, gin.H{
- "msg": "请求资源不存在",
- "code": 4999,
- "data": nil,
- })
- })
-}
-
-func ListShortLinksAPI() gin.HandlerFunc {
- return Authenticator(func(c *gin.Context, user *models.User) {
- var page = utils.GetIntQueryValue(c, "page", 1)
- var pageSize = utils.GetIntQueryValue(c, "pageSize", 20)
- start := int64((page - 1) * pageSize)
- stop := start - 1 + int64(pageSize)
-
- var key string
- if user.IsAdmin() {
- key = utils.GetShortLinksKey()
- } else {
- key = utils.GetUserShortLinksKey(user.Username)
- }
-
- slRepo := repository.GetShortLinkRepo(db.GetRedisClient())
- result, err := slRepo.List(key, start, stop)
- if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
- return
- }
-
- c.JSON(http.StatusOK, gin.H{
- "msg": "",
- "code": 0,
- "data": result,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("请求资源不存在"))
})
}
diff --git a/internal/app/handlers/user.go b/internal/app/handlers/user.go
index 649b826..0254a51 100644
--- a/internal/app/handlers/user.go
+++ b/internal/app/handlers/user.go
@@ -10,95 +10,98 @@ import (
"strings"
)
-type loginForm struct {
- Username string `json:"username" binding:"required"`
- Password string `json:"password" binding:"required"`
-}
-
-func Login(c *gin.Context) {
- f := &loginForm{}
+// LoginAPI godoc
+// @Summary 账号登入
+// @Description 账号密码登入
+// @Tags 账号
+// @Accept json
+// @Produce json
+// @Param body body models.LoginAPIRequest true "登入请求"
+// @Success 200 {object} models.Response{data=models.LoginAPIResponseData}
+// @Router /user/login [post]
+func LoginAPI(c *gin.Context) {
+ f := &models.LoginAPIRequest{}
err := c.BindJSON(f)
if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": "用户名或密码错误",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("用户名或密码错误"))
return
}
repo := repository.GetUserRepo(db.GetRedisClient())
u, err := repo.FindOneByUsername(strings.TrimSpace(f.Username))
if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": "用户名或密码错误",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("用户名或密码错误"))
return
}
dk, _ := utils.EncodePassword([]byte(f.Password), u.Salt)
if string(u.Password) != string(dk) {
- c.JSON(http.StatusOK, gin.H{
- "msg": "用户名或密码错误",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("用户名或密码错误"))
return
}
- c.JSON(http.StatusOK, gin.H{
- "msg": "ok",
- "code": 0,
- "data": gin.H{
- "token": utils.GenerateJWT(u.Username),
- },
- })
+ c.JSON(http.StatusOK, models.NewSuccessResponse(models.LoginAPIResponseData{
+ Token: utils.GenerateJWT(u.Username),
+ }))
}
+// GetUserInfoAPI godoc
+// @Security ApiKeyAuth
+// @Summary 获取账号信息
+// @Description 获取账号信息
+// @Tags 账号
+// @Accept json
+// @Produce json
+// @Success 200 {object} models.Response{data=models.GetUserInfoAPIResponseData}
+// @Failure 401
+// @Router /user/info [get]
func GetUserInfoAPI() gin.HandlerFunc {
return Authenticator(func(c *gin.Context, user *models.User) {
- c.JSON(http.StatusOK, gin.H{
- "msg": "",
- "code": 0,
- "data": gin.H{
- "username": user.Username,
- "role": user.Role,
- },
- })
+ c.JSON(http.StatusOK, models.NewSuccessResponse(models.GetUserInfoAPIResponseData{
+ Username: user.Username,
+ Role: user.Role,
+ }))
})
}
+// LogoutAPI godoc
+// @Security ApiKeyAuth
+// @Summary 登出
+// @Description 登出
+// @Tags 账号
+// @Accept json
+// @Produce json
+// @Success 200 {object} models.Response
+// @Failure 401
+// @Router /user/logout [post]
func LogoutAPI() gin.HandlerFunc {
return Authenticator(func(c *gin.Context, user *models.User) {
- c.JSON(http.StatusOK, gin.H{
- "msg": "",
- "code": 0,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewSuccessResponse(nil))
})
}
+// ChangePasswordAPI godoc
+// @Security ApiKeyAuth
+// @Summary 修改账号密码
+// @Description 修改账号密码
+// @Tags 账号
+// @Accept json
+// @Produce json
+// @Param body body models.ChangePasswordAPIRequest true "修改密码请求"
+// @Success 200 {object} models.Response
+// @Failure 401
+// @Router /user/change-password [post]
func ChangePasswordAPI() gin.HandlerFunc {
return Authenticator(func(c *gin.Context, user *models.User) {
- p := &models.ChangePasswordParameter{}
+ p := &models.ChangePasswordAPIRequest{}
if err := c.ShouldBindJSON(p); err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": "请填写原密码和新密码",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("请填写原密码和新密码"))
return
}
dk, _ := utils.EncodePassword([]byte(p.Password), user.Salt)
if string(user.Password) != string(dk) {
- c.JSON(http.StatusOK, gin.H{
- "msg": "原密码错误",
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse("原密码错误"))
return
}
@@ -107,18 +110,10 @@ func ChangePasswordAPI() gin.HandlerFunc {
repo := repository.GetUserRepo(db.GetRedisClient())
err := repo.UpdatePassword(user)
if err != nil {
- c.JSON(http.StatusOK, gin.H{
- "msg": err.Error(),
- "code": 4999,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewErrorResponse(err.Error()))
return
}
- c.JSON(http.StatusOK, gin.H{
- "msg": "ok",
- "code": 0,
- "data": nil,
- })
+ c.JSON(http.StatusOK, models.NewSuccessResponse(nil))
})
}
diff --git a/internal/app/models/models.go b/internal/app/models/models.go
index dab7f9f..c3aad0c 100644
--- a/internal/app/models/models.go
+++ b/internal/app/models/models.go
@@ -2,6 +2,7 @@ package models
import (
"encoding/json"
+ "github.com/jwma/jump-jump/internal/app/config"
"time"
)
@@ -13,11 +14,65 @@ var Roles = map[int]string{
RoleAdmin: "admin",
}
-type ChangePasswordParameter struct {
- Password string `json:"password"`
- NewPassword string `json:"newPassword"`
+type Response struct {
+ Msg string `json:"msg" example:"ok" default:"ok"`
+ Code int `json:"code" example:"0" format:"int" default:"0"`
+ Data interface{} `json:"data"`
+} // @name Response
+
+func NewSuccessResponse(data interface{}) *Response {
+ return &Response{
+ Msg: "ok",
+ Code: 0,
+ Data: data,
+ }
+}
+
+func NewErrorResponse(msg string) *Response {
+ return &Response{
+ Msg: msg,
+ Code: 4999,
+ Data: nil,
+ }
}
+type LoginAPIRequest struct {
+ // 用户名
+ Username string `json:"username" binding:"required" example:"your_username"`
+
+ // 密码
+ Password string `json:"password" binding:"required" example:"your_password"`
+} // @name LoginAPIRequest
+
+type LoginAPIResponseData struct {
+ // json web token
+ Token string `json:"token,omitempty" example:"xxx.xxx.xxx"`
+} // @name LoginAPIResponseData
+
+type GetUserInfoAPIResponseData struct {
+ // 用户名
+ Username string `json:"username" example:"admin"`
+
+ // 角色,1 普通用户 | 2 管理员
+ Role int `json:"role" example:"1" enums:"1,2"`
+} // @name GetUserInfoAPIResponseData
+
+type ChangePasswordAPIRequest struct {
+ // 原密码
+ Password string `json:"password"`
+
+ // 新密码
+ NewPassword string `json:"newPassword"`
+} // @name ChangePasswordAPIRequest
+
+type GetConfigAPIResponseData struct {
+ Config *config.SystemConfig `json:"config"`
+} // @name GetConfigAPIResponseData
+
+type UpdateLandingHostsAPIRequest struct {
+ Hosts []string `json:"hosts" format:"array" example:"https://a.com/,https://b.com/"`
+} // @name UpdateLandingHostsAPIRequest
+
type User struct {
Username string `json:"username"`
Role int `json:"role"`
@@ -32,7 +87,7 @@ func (u *User) IsAdmin() bool {
}
type ShortLink struct {
- Id string `json:"id"`
+ Id string `json:"id" `
Url string `json:"url"`
Description string `json:"description"`
IsEnable bool `json:"is_enable"`
@@ -41,17 +96,102 @@ type ShortLink struct {
UpdateTime time.Time `json:"update_time"`
}
-type CreateShortLinkParameter struct {
- *ShortLink
- IdLength int `json:"id_length"`
+func NewShortLink(createdBy string, r *CreateShortLinkAPIRequest) *ShortLink {
+ return &ShortLink{
+ Id: r.Id,
+ Url: r.Url,
+ Description: r.Description,
+ IsEnable: r.IsEnable,
+ CreatedBy: createdBy,
+ }
+}
+
+type ShortLinkData struct {
+ Id string `json:"id" example:"RANDOM_ID" format:"string"`
+ // 目标链接
+ Url string `json:"url" example:"https://github.com/jwma/jump-jump" format:"string"`
+
+ // 描述
+ Description string `json:"description" example:"Jump Jump project" format:"string"`
+
+ // 是否启用
+ IsEnable bool `json:"isEnable" example:"true" format:"boolean"`
+
+ // 创建者
+ CreatedBy string `json:"createdBy" example:"admin" format:"string"`
+
+ // 创建时间
+ CreateTime time.Time `json:"createTime"`
+
+ // 最后更新时间
+ UpdateTime time.Time `json:"updateTime"`
+} // @name ShortLinkData
+
+func ToShortLinkData(s *ShortLink) *ShortLinkData {
+ return &ShortLinkData{
+ Id: s.Id,
+ Url: s.Url,
+ Description: s.Description,
+ IsEnable: s.IsEnable,
+ CreatedBy: s.CreatedBy,
+ CreateTime: s.CreateTime,
+ UpdateTime: s.UpdateTime,
+ }
}
-type UpdateShortLinkParameter struct {
- Url string `json:"url" binding:"required"`
- Description string `json:"description"`
- IsEnable bool `json:"is_enable"`
+func ToShortLinkDataSlice(s []*ShortLink) []*ShortLinkData {
+ r := make([]*ShortLinkData, 0)
+ for _, ss := range s {
+ r = append(r, ToShortLinkData(ss))
+ }
+ return r
}
+type CreateShortLinkAPIRequest struct {
+ // 只有管理员可以在创建的时候指定 ID
+ Id string `json:"id" format:"string" example:"RANDOM_ID"`
+
+ // 目标链接
+ Url string `json:"url" example:"https://github.com/jwma/jump-jump"`
+
+ // 描述
+ Description string `json:"description" example:"Jump Jump project"`
+
+ // 是否启用
+ IsEnable bool `json:"isEnable" example:"true" format:"boolean"`
+
+ // 短链接 ID 长度
+ IdLength int `json:"idLength" example:"4" format:"int"`
+} // @name CreateShortLinkAPIRequest
+
+type GetShortLinkAPIResponseData struct {
+ ShortLinkData *ShortLinkData `json:"shortLink"`
+} // @name GetShortLinkAPIResponseData
+
+type CreateShortLinkAPIResponseData struct {
+ ShortLinkData *ShortLinkData `json:"shortLink"`
+} // @name CreateShortLinkAPIResponseData
+
+type UpdateShortLinkAPIResponseData struct {
+ ShortLinkData *ShortLinkData `json:"shortLink"`
+} // @name UpdateShortLinkAPIResponseData
+
+type UpdateShortLinkAPIRequest struct {
+ // 目标链接
+ Url string `json:"url" binding:"required" example:"https://github.com/jwma/jump-jump"`
+
+ // 描述
+ Description string `json:"description" example:"Jump Jump project"`
+
+ // 是否启用
+ IsEnable bool `json:"isEnable" example:"true" format:"boolean"`
+} // @name UpdateShortLinkAPIRequest
+
+type ListShortLinksAPIResponseData struct {
+ ShortLinks []*ShortLinkData `json:"shortLinks"`
+ Total int64 `json:"total" example:"10" format:"10"`
+} // @name ListShortLinksAPIResponseData
+
type RequestHistory struct {
Id string `json:"id"`
Link *ShortLink `json:"-"`
@@ -59,7 +199,7 @@ type RequestHistory struct {
IP string `json:"ip"`
UA string `json:"ua"`
Time time.Time `json:"time"`
-}
+} // @name RequestHistory
func (r *RequestHistory) MarshalBinary() (data []byte, err error) {
return json.Marshal(r)
@@ -69,6 +209,10 @@ func NewRequestHistory(link *ShortLink, IP string, UA string) *RequestHistory {
return &RequestHistory{Link: link, IP: IP, UA: UA, Url: link.Url}
}
+type ShortLinkDataAPIResponseData struct {
+ Histories []*RequestHistory `json:"histories"`
+} // @name ShortLinkDataAPIResponseData
+
type ActiveLink struct {
Id string
Time time.Time
diff --git a/internal/app/repository/repository.go b/internal/app/repository/repository.go
index 6009eee..3432980 100644
--- a/internal/app/repository/repository.go
+++ b/internal/app/repository/repository.go
@@ -251,7 +251,7 @@ func (r *shortLinkRepository) Save(s *models.ShortLink) error {
return r.save(s, false)
}
-func (r *shortLinkRepository) Update(s *models.ShortLink, params *models.UpdateShortLinkParameter) error {
+func (r *shortLinkRepository) Update(s *models.ShortLink, params *models.UpdateShortLinkAPIRequest) error {
s.Url = params.Url
s.Description = params.Description
s.IsEnable = params.IsEnable
diff --git a/internal/app/repository/repository_test.go b/internal/app/repository/repository_test.go
index 038f096..40ca5fc 100644
--- a/internal/app/repository/repository_test.go
+++ b/internal/app/repository/repository_test.go
@@ -56,7 +56,7 @@ func TestShortLinkRepository_Update(t *testing.T) {
t.Error(err)
}
- params := &models.UpdateShortLinkParameter{
+ params := &models.UpdateShortLinkAPIRequest{
Url: "http://github.com/jwma",
Description: "安木鸡的 Github",
IsEnable: true,
diff --git a/internal/app/routers/router.go b/internal/app/routers/router.go
index fbfc3c2..f92c021 100644
--- a/internal/app/routers/router.go
+++ b/internal/app/routers/router.go
@@ -3,13 +3,71 @@ package routers
import (
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
+ docs "github.com/jwma/jump-jump/docs"
"github.com/jwma/jump-jump/internal/app/handlers"
+ swaggerFiles "github.com/swaggo/files"
+ ginSwagger "github.com/swaggo/gin-swagger"
"net/http"
+ "os"
+ "strings"
)
+// @securityDefinitions.apikey ApiKeyAuth
+// @in header
+// @name Authorization
+
+// @contact.name MJ Ma
+// @contact.url https://www.linkedin.com/in/mj-profile/
+// @contact.email m.mjw.ma@gmail.com
+
+// @license.name MIT
+// @license.url https://github.com/jwma/jump-jump/blob/master/LICENSE
+
+func getAPIDocBasicAccounts() gin.Accounts {
+ defaultUsername := "apidoc"
+ defaultPassword := "showmethedoc"
+
+ u := os.Getenv("API_DOC_USERNAME")
+ p := os.Getenv("API_DOC_PASSWORD")
+
+ if u == "" || p == "" {
+ return gin.Accounts{defaultUsername: defaultPassword}
+ }
+
+ return gin.Accounts{u: p}
+}
+
+func detectAPIDocHost() {
+ // 如果通过该环境变量指明了 API 文档使用的 Host,则直接使用
+ h := os.Getenv("API_DOC_HOST")
+ if h != "" {
+ docs.SwaggerInfo.Host = h
+ return
+ }
+
+ if gin.Mode() == gin.DebugMode {
+ docs.SwaggerInfo.Host = os.Getenv("J2_API_ADDR")
+ } else {
+ docs.SwaggerInfo.Host = strings.Split(os.Getenv("ALLOWED_HOSTS"), ",")[0]
+ }
+}
+
func SetupRouter() *gin.Engine {
r := gin.Default()
+ // Swagger
+ docs.SwaggerInfo.Title = "Jump Jump API Documentation"
+ docs.SwaggerInfo.Description = "🚀🚀🚀"
+ docs.SwaggerInfo.Version = "v1"
+ docs.SwaggerInfo.BasePath = "/v1"
+ docs.SwaggerInfo.Schemes = []string{"http", "https"}
+ url := ginSwagger.URL("/swagger/doc.json")
+ detectAPIDocHost()
+ docsR := r.Group("/swagger", gin.BasicAuth(getAPIDocBasicAccounts()))
+ {
+ docsR.GET("/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
+ }
+
if gin.Mode() == gin.DebugMode { // 开发环境下,开启 CORS
corsCfg := cors.DefaultConfig()
corsCfg.AllowAllOrigins = true
@@ -19,33 +77,38 @@ func SetupRouter() *gin.Engine {
r.Use(handlers.AllowedHostsMiddleware())
+ // serve dashboard static resources
r.LoadHTMLFiles("./web/admin/index.html")
r.StaticFS("/static", http.Dir("./web/admin/static"))
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{})
})
- r.POST("/v1/user/login", handlers.Login)
- r.GET("/v1/user/info", handlers.JWTAuthenticatorMiddleware(), handlers.GetUserInfoAPI())
- r.POST("/v1/user/logout", handlers.JWTAuthenticatorMiddleware(), handlers.LogoutAPI())
- r.PATCH("/v1/user/change-password", handlers.JWTAuthenticatorMiddleware(), handlers.ChangePasswordAPI())
-
- r.GET("/v1/config", handlers.GetConfig)
- r.PATCH("/v1/config/landing-hosts", handlers.JWTAuthenticatorMiddleware(),
- handlers.UpdateLandingHostsAPI())
- r.PATCH("/v1/config/id-length", handlers.JWTAuthenticatorMiddleware(),
- handlers.UpdateIdLengthConfigAPI())
- r.PATCH("/v1/config/short-link-404-handling", handlers.JWTAuthenticatorMiddleware(),
- handlers.UpdateShortLinkNotFoundConfigAPI())
-
- shortLinkAPI := r.Group("/v1/short-link")
- shortLinkAPI.Use(handlers.JWTAuthenticatorMiddleware())
- shortLinkAPI.GET("/", handlers.ListShortLinksAPI())
- shortLinkAPI.GET("/:id", handlers.GetShortLinkAPI())
- shortLinkAPI.POST("/", handlers.CreateShortLinkAPI())
- shortLinkAPI.PATCH("/:id", handlers.UpdateShortLinkAPI())
- shortLinkAPI.DELETE("/:id", handlers.DeleteShortLinkAPI())
- shortLinkAPI.GET("/:id/*action", handlers.ShortLinkActionAPI())
+ // v1 API's
+ v1 := r.Group("/v1")
+ {
+ // account stuff
+ v1.POST("/user/login", handlers.LoginAPI)
+ v1.GET("/user/info", handlers.JWTAuthenticatorMiddleware(), handlers.GetUserInfoAPI())
+ v1.POST("/user/logout", handlers.JWTAuthenticatorMiddleware(), handlers.LogoutAPI())
+ v1.POST("/user/change-password", handlers.JWTAuthenticatorMiddleware(), handlers.ChangePasswordAPI())
+
+ // system configuration stuff
+ v1.GET("/config", handlers.JWTAuthenticatorMiddleware(), handlers.GetConfigAPI)
+ v1.PATCH("/config/landing-hosts", handlers.JWTAuthenticatorMiddleware(), handlers.UpdateLandingHostsAPI())
+ v1.PATCH("/config/id-length", handlers.JWTAuthenticatorMiddleware(), handlers.UpdateIdLengthConfigAPI())
+ v1.PATCH("/config/short-link-404-handling", handlers.JWTAuthenticatorMiddleware(), handlers.UpdateShortLinkNotFoundConfigAPI())
+
+ // short link stuff
+ shortLinkAPI := v1.Group("/short-link")
+ shortLinkAPI.Use(handlers.JWTAuthenticatorMiddleware())
+ shortLinkAPI.GET("/", handlers.ListShortLinksAPI())
+ shortLinkAPI.GET("/:id", handlers.GetShortLinkAPI())
+ shortLinkAPI.POST("/", handlers.CreateShortLinkAPI())
+ shortLinkAPI.PATCH("/:id", handlers.UpdateShortLinkAPI())
+ shortLinkAPI.DELETE("/:id", handlers.DeleteShortLinkAPI())
+ shortLinkAPI.GET("/:id/*action", handlers.ShortLinkActionAPI())
+ }
return r
}
diff --git a/web/admin/index.html b/web/admin/index.html
index ba5813d..957b8ef 100644
--- a/web/admin/index.html
+++ b/web/admin/index.html
@@ -1 +1 @@
-
Jump Jump Admin
\ No newline at end of file
+Jump Jump Admin
\ No newline at end of file
diff --git a/web/admin/static/css/chunk-13714370.2672e5fe.css b/web/admin/static/css/chunk-13714370.2672e5fe.css
new file mode 100644
index 0000000..2a38215
--- /dev/null
+++ b/web/admin/static/css/chunk-13714370.2672e5fe.css
@@ -0,0 +1 @@
+.paginator-container[data-v-901f7d5c]{margin-top:10px}
\ No newline at end of file
diff --git a/web/admin/static/css/chunk-60a4aa86.68815401.css b/web/admin/static/css/chunk-60a4aa86.68815401.css
deleted file mode 100644
index aac31f5..0000000
--- a/web/admin/static/css/chunk-60a4aa86.68815401.css
+++ /dev/null
@@ -1 +0,0 @@
-.paginator-container[data-v-23d33577]{margin-top:10px}
\ No newline at end of file
diff --git a/web/admin/static/js/app.2389be4d.js b/web/admin/static/js/app.841517a2.js
similarity index 68%
rename from web/admin/static/js/app.2389be4d.js
rename to web/admin/static/js/app.841517a2.js
index 82f3424..eb93766 100644
--- a/web/admin/static/js/app.2389be4d.js
+++ b/web/admin/static/js/app.841517a2.js
@@ -1 +1 @@
-(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["app"],{0:function(e,t,n){e.exports=n("56d7")},"028b":function(e,t,n){"use strict";var a=n("f12c"),s=n.n(a);s.a},"031b":function(e,t,n){},"186a":function(e,t,n){"use strict";var a=n("dc52"),s=n.n(a);s.a},"18f0":function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-link",use:"icon-link-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(o);t["default"]=o},2995:function(e,t,n){},"2a3d":function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-password",use:"icon-password-usage",viewBox:"0 0 128 128",content:''});r.a.add(o);t["default"]=o},3289:function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-list",use:"icon-list-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(o);t["default"]=o},"34c8":function(e,t,n){"use strict";var a=n("88a1"),s=n.n(a);s.a},4360:function(e,t,n){"use strict";var a=n("2b0e"),s=n("2f62"),i=(n("b54a"),n("7f7f"),{sidebar:function(e){return e.app.sidebar},device:function(e){return e.app.device},token:function(e){return e.user.token},name:function(e){return e.user.name},role:function(e){return e.user.role},pinned:function(e){return e.link.pinned}}),r=i,o=n("a78e"),c=n.n(o),u={sidebar:{opened:!c.a.get("sidebarStatus")||!!+c.a.get("sidebarStatus"),withoutAnimation:!1},device:"desktop"},d={TOGGLE_SIDEBAR:function(e){e.sidebar.opened=!e.sidebar.opened,e.sidebar.withoutAnimation=!1,e.sidebar.opened?c.a.set("sidebarStatus",1):c.a.set("sidebarStatus",0)},CLOSE_SIDEBAR:function(e,t){c.a.set("sidebarStatus",0),e.sidebar.opened=!1,e.sidebar.withoutAnimation=t},TOGGLE_DEVICE:function(e,t){e.device=t}},l={toggleSideBar:function(e){var t=e.commit;t("TOGGLE_SIDEBAR")},closeSideBar:function(e,t){var n=e.commit,a=t.withoutAnimation;n("CLOSE_SIDEBAR",a)},toggleDevice:function(e,t){var n=e.commit;n("TOGGLE_DEVICE",t)}},f={namespaced:!0,state:u,mutations:d,actions:l},h=n("83d6"),m=n.n(h),b=m.a.showSettings,p=m.a.fixedHeader,v=m.a.sidebarLogo,g={showSettings:b,fixedHeader:p,sidebarLogo:v},j={CHANGE_SETTING:function(e,t){var n=t.key,a=t.value;e.hasOwnProperty(n)&&(e[n]=a)}},w={changeSetting:function(e,t){var n=e.commit;n("CHANGE_SETTING",t)}},k={namespaced:!0,state:g,mutations:j,actions:w},y=n("c24f"),x=n("5f87"),_=n("a18c"),C=function(){return{token:Object(x["a"])(),name:"",role:1}},O=C(),z={RESET_STATE:function(e){Object.assign(e,C())},SET_TOKEN:function(e,t){e.token=t},SET_NAME:function(e,t){e.name=t},SET_ROLE:function(e,t){e.role=t}},S={login:function(e,t){var n=e.commit,a=t.username,s=t.password;return new Promise((function(e,t){Object(y["c"])({username:a.trim(),password:s}).then((function(t){var a=t.data;n("SET_TOKEN",a.token),Object(x["c"])(a.token),e()})).catch((function(e){t(e)}))}))},getInfo:function(e){var t=e.commit;e.state;return new Promise((function(e,n){Object(y["b"])().then((function(a){var s=a.data;s||n("登入信息验证失败,请重新登入");var i=s.username,r=s.role;t("SET_NAME",i),t("SET_ROLE",r),e(s)})).catch((function(e){n(e)}))}))},logout:function(e){var t=e.commit,n=e.state;return new Promise((function(e,a){Object(y["d"])(n.token).then((function(){Object(x["b"])(),Object(_["b"])(),t("RESET_STATE"),e()})).catch((function(e){a(e)}))}))},resetToken:function(e){var t=e.commit;return new Promise((function(e){Object(x["b"])(),t("RESET_STATE"),e()}))}},E={namespaced:!0,state:O,mutations:z,actions:S},M="pinned",B={pinned:JSON.parse(localStorage.getItem(M)||"[]")},T={PIN:function(e,t){e.pinned.push(t)},UNPIN:function(e,t){e.pinned.indexOf(t)>=0&&e.pinned.splice(e.pinned.indexOf(t),1)}},L={pin:function(e,t){var n=e.commit,a=e.state;n("PIN",t),localStorage.setItem(M,JSON.stringify(a.pinned))},unpin:function(e,t){var n=e.commit,a=e.state;n("UNPIN",t),localStorage.setItem(M,JSON.stringify(a.pinned))}},$={namespaced:!0,state:B,mutations:T,actions:L};a["default"].use(s["a"]);var A=new s["a"].Store({modules:{app:f,settings:k,user:E,link:$},getters:r});t["a"]=A},4678:function(e,t,n){var a={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-SG":"cdab","./en-SG.js":"cdab","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-nz":"6f50","./en-nz.js":"6f50","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf75","./tlh.js":"cf75","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-tw":"90ea","./zh-tw.js":"90ea"};function s(e){var t=i(e);return n(t)}function i(e){var t=a[e];if(!(t+1)){var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}return t}s.keys=function(){return Object.keys(a)},s.resolve=i,e.exports=s,s.id="4678"},"4cdc":function(e,t,n){},"4df5":function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-eye",use:"icon-eye-usage",viewBox:"0 0 128 64",content:''});r.a.add(o);t["default"]=o},"51ff":function(e,t,n){var a={"./add.svg":"c2a3","./dashboard.svg":"f782","./eye-open.svg":"d7ec","./eye.svg":"4df5","./form.svg":"eb1b","./github.svg":"558d","./link.svg":"18f0","./list.svg":"3289","./password.svg":"2a3d","./user.svg":"b3b5"};function s(e){var t=i(e);return n(t)}function i(e){var t=a[e];if(!(t+1)){var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}return t}s.keys=function(){return Object.keys(a)},s.resolve=i,e.exports=s,s.id="51ff"},"558d":function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-github",use:"icon-github-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(o);t["default"]=o},"56d7":function(e,t,n){"use strict";n.r(t);n("cadf"),n("551c"),n("f751"),n("097d");var a=n("2b0e"),s=n("c1df"),i=n.n(s),r=(n("f5df"),n("5c96")),o=n.n(r),c=(n("0fae"),n("b20f"),function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"app"}},[n("router-view")],1)}),u=[],d={name:"App"},l=d,f=n("2877"),h=Object(f["a"])(l,c,u,!1,null,null,null),m=h.exports,b=n("4360"),p=n("a18c"),v=(n("ac6a"),function(){var e=this,t=e.$createElement,n=e._self._c||t;return e.isExternal?n("div",e._g({staticClass:"svg-external-icon svg-icon",style:e.styleExternalIcon},e.$listeners)):n("svg",e._g({class:e.svgClass,attrs:{"aria-hidden":"true"}},e.$listeners),[n("use",{attrs:{href:e.iconName}})])}),g=[],j=n("61f7"),w={name:"SvgIcon",props:{iconClass:{type:String,required:!0},className:{type:String,default:""}},computed:{isExternal:function(){return Object(j["a"])(this.iconClass)},iconName:function(){return"#icon-".concat(this.iconClass)},svgClass:function(){return this.className?"svg-icon "+this.className:"svg-icon"},styleExternalIcon:function(){return{mask:"url(".concat(this.iconClass,") no-repeat 50% 50%"),"-webkit-mask":"url(".concat(this.iconClass,") no-repeat 50% 50%")}}}},k=w,y=(n("d1a7"),Object(f["a"])(k,v,g,!1,null,"4342976c",null)),x=y.exports;a["default"].component("svg-icon",x);var _=n("51ff"),C=function(e){return e.keys().map(e)};C(_);n("7f7f"),n("96cf");var O=n("3b8d"),z=n("323e"),S=n.n(z),E=(n("a5d8"),n("5f87")),M=n("83d6"),B=n.n(M),T=B.a.title||"Vue Admin Template";function L(e){return e?"".concat(e," - ").concat(T):"".concat(T)}S.a.configure({showSpinner:!1});var $=["/login"];p["a"].beforeEach(function(){var e=Object(O["a"])(regeneratorRuntime.mark((function e(t,n,a){var s,i;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:if(S.a.start(),document.title=L(t.meta.title),s=Object(E["a"])(),!s){e.next=29;break}if("/login"!==t.path){e.next=9;break}a({path:"/"}),S.a.done(),e.next=27;break;case 9:if(i=b["a"].getters.name,!i){e.next=14;break}a(),e.next=27;break;case 14:return e.prev=14,e.next=17,b["a"].dispatch("user/getInfo");case 17:a(),e.next=27;break;case 20:return e.prev=20,e.t0=e["catch"](14),e.next=24,b["a"].dispatch("user/resetToken");case 24:r["Message"].error(e.t0||"Has Error"),a("/login?redirect=".concat(t.path)),S.a.done();case 27:e.next=30;break;case 29:-1!==$.indexOf(t.path)?a():(a("/login?redirect=".concat(t.path)),S.a.done());case 30:case"end":return e.stop()}}),e,null,[[14,20]])})));return function(t,n,a){return e.apply(this,arguments)}}()),p["a"].afterEach((function(){S.a.done()})),a["default"].filter("dateformat",(function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"YYYY-MM-DD HH:mm:ss";return e?i()(e).format(t):"-"})),a["default"].use(o.a),a["default"].config.productionTip=!1,new a["default"]({el:"#app",router:p["a"],store:b["a"],render:function(e){return e(m)}})},"5f87":function(e,t,n){"use strict";n.d(t,"a",(function(){return r})),n.d(t,"c",(function(){return o})),n.d(t,"b",(function(){return c}));var a=n("a78e"),s=n.n(a),i="j2_token";function r(){return s.a.get(i)}function o(e){return s.a.set(i,e)}function c(){return s.a.remove(i)}},"61f7":function(e,t,n){"use strict";n.d(t,"a",(function(){return a})),n.d(t,"c",(function(){return s})),n.d(t,"b",(function(){return r}));n("3b2b");function a(e){return/^(https?:|mailto:|tel:)/.test(e)}function s(e){return e.length>=2}var i=new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|localhost|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\#[-a-z\\d_\\/]*)?(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$","i");function r(e){return!!i.test(e)}},"6b31":function(e,t,n){"use strict";var a=n("4cdc"),s=n.n(a);s.a},"83d6":function(e,t){e.exports={title:"Jump Jump Admin",fixedHeader:!1,sidebarLogo:!1}},"88a1":function(e,t,n){},8902:function(e,t,n){},"9f2b":function(e,t,n){"use strict";var a=n("bf90"),s=n.n(a);s.a},"9f43":function(e,t,n){"use strict";var a=n("2995"),s=n.n(a);s.a},a18c:function(e,t,n){"use strict";var a,s,i=n("2b0e"),r=n("8c4f"),o=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-wrapper",class:e.classObj},["mobile"===e.device&&e.sidebar.opened?n("div",{staticClass:"drawer-bg",on:{click:e.handleClickOutside}}):e._e(),e._v(" "),n("sidebar",{staticClass:"sidebar-container"}),e._v(" "),n("div",{staticClass:"main-container"},[n("div",{class:{"fixed-header":e.fixedHeader}},[n("navbar")],1),e._v(" "),n("app-main")],1)],1)},c=[],u=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"navbar"},[n("hamburger",{staticClass:"hamburger-container",attrs:{"is-active":e.sidebar.opened},on:{toggleClick:e.toggleSideBar}}),e._v(" "),n("breadcrumb",{staticClass:"breadcrumb-container"}),e._v(" "),n("div",{staticClass:"right-menu"},[n("el-dropdown",{staticClass:"username-container",attrs:{trigger:"click"}},[n("div",{staticClass:"username-wrapper"},[n("span",{staticStyle:{cursor:"pointer"}},[e._v(e._s(e.name))])]),e._v(" "),n("el-dropdown-menu",{staticClass:"user-dropdown",attrs:{slot:"dropdown"},slot:"dropdown"},[n("router-link",{attrs:{to:"/"}},[n("el-dropdown-item",[e._v("首页")])],1),e._v(" "),n("router-link",{attrs:{to:"/security/change-password"}},[n("el-dropdown-item",[e._v("修改密码")])],1),e._v(" "),n("a",{attrs:{target:"_blank",href:"https://github.com/jwma/jump-jump"}},[n("el-dropdown-item",[e._v("Github")])],1),e._v(" "),n("el-dropdown-item",{attrs:{divided:""},nativeOn:{click:function(t){return e.logout(t)}}},[n("span",{staticStyle:{display:"block"}},[e._v("登出")])])],1)],1)],1)],1)},d=[],l=(n("96cf"),n("3b8d")),f=n("db72"),h=n("2f62"),m=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("el-breadcrumb",{staticClass:"app-breadcrumb",attrs:{separator:"/"}},[n("transition-group",{attrs:{name:"breadcrumb"}},e._l(e.levelList,(function(t,a){return n("el-breadcrumb-item",{key:t.path},["noRedirect"===t.redirect||a==e.levelList.length-1?n("span",{staticClass:"no-redirect"},[e._v(e._s(t.meta.title))]):n("a",{on:{click:function(n){return n.preventDefault(),e.handleLink(t)}}},[e._v(e._s(t.meta.title))])])})),1)],1)},b=[],p=(n("7f7f"),n("bd11")),v=n.n(p),g={data:function(){return{levelList:null}},watch:{$route:function(){this.getBreadcrumb()}},created:function(){this.getBreadcrumb()},methods:{getBreadcrumb:function(){var e=this.$route.matched.filter((function(e){return e.meta&&e.meta.title})),t=e[0];this.isDashboard(t)||(e=[{path:"/dashboard",meta:{title:"Dashboard"}}].concat(e)),this.levelList=e.filter((function(e){return e.meta&&e.meta.title&&!1!==e.meta.breadcrumb}))},isDashboard:function(e){var t=e&&e.name;return!!t&&t.trim().toLocaleLowerCase()==="Dashboard".toLocaleLowerCase()},pathCompile:function(e){var t=this.$route.params,n=v.a.compile(e);return n(t)},handleLink:function(e){var t=e.redirect,n=e.path;t?this.$router.push(t):this.$router.push(this.pathCompile(n))}}},j=g,w=(n("34c8"),n("2877")),k=Object(w["a"])(j,m,b,!1,null,"62cc9144",null),y=k.exports,x=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticStyle:{padding:"0 15px"},on:{click:e.toggleClick}},[n("svg",{staticClass:"hamburger",class:{"is-active":e.isActive},attrs:{viewBox:"0 0 1024 1024",xmlns:"http://www.w3.org/2000/svg",width:"64",height:"64"}},[n("path",{attrs:{d:"M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"}})])])},_=[],C={name:"Hamburger",props:{isActive:{type:Boolean,default:!1}},methods:{toggleClick:function(){this.$emit("toggleClick")}}},O=C,z=(n("186a"),Object(w["a"])(O,x,_,!1,null,"49e15297",null)),S=z.exports,E={components:{Breadcrumb:y,Hamburger:S},computed:Object(f["a"])({},Object(h["b"])(["sidebar","name"])),methods:{toggleSideBar:function(){this.$store.dispatch("app/toggleSideBar")},logout:function(){var e=Object(l["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.next=2,this.$store.dispatch("user/logout");case 2:this.$router.push("/login?redirect=".concat(this.$route.fullPath));case 3:case"end":return e.stop()}}),e,this)})));function t(){return e.apply(this,arguments)}return t}()}},M=E,B=(n("9f43"),Object(w["a"])(M,u,d,!1,null,"26745010",null)),T=B.exports,L=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{class:{"has-logo":e.showLogo}},[e.showLogo?n("logo",{attrs:{collapse:e.isCollapse}}):e._e(),e._v(" "),n("el-scrollbar",{attrs:{"wrap-class":"scrollbar-wrapper"}},[n("el-menu",{attrs:{"default-active":e.activeMenu,collapse:e.isCollapse,"background-color":e.variables.menuBg,"text-color":e.variables.menuText,"unique-opened":!1,"active-text-color":e.variables.menuActiveText,"collapse-transition":!1,mode:"vertical"}},e._l(e.routes,(function(e){return n("sidebar-item",{key:e.path,attrs:{item:e,"base-path":e.path}})})),1)],1)],1)},$=[],A=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"sidebar-logo-container",class:{collapse:e.collapse}},[n("transition",{attrs:{name:"sidebarLogoFade"}},[e.collapse?n("router-link",{key:"collapse",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])]):n("router-link",{key:"expand",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):e._e(),e._v(" "),n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])])],1)],1)},H=[],N={name:"SidebarLogo",props:{collapse:{type:Boolean,required:!0}},data:function(){return{title:"Vue Admin Template",logo:"https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png"}}},I=N,P=(n("6b31"),Object(w["a"])(I,A,H,!1,null,"5bb1c0e2",null)),D=P.exports,q=function(){var e=this,t=e.$createElement,n=e._self._c||t;return e.item.hidden?e._e():n("div",[!e.hasOneShowingChild(e.item.children,e.item)||e.onlyOneChild.children&&!e.onlyOneChild.noShowingChildren||e.item.alwaysShow?n("el-submenu",{ref:"subMenu",attrs:{index:e.resolvePath(e.item.path),"popper-append-to-body":""}},[n("template",{slot:"title"},[e.item.meta?n("item",{attrs:{icon:e.item.meta&&e.item.meta.icon,title:e.item.meta.title}}):e._e()],1),e._v(" "),e._l(e.item.children,(function(t){return n("sidebar-item",{key:t.path,staticClass:"nest-menu",attrs:{"is-nest":!0,item:t,"base-path":e.resolvePath(t.path)}})}))],2):[e.onlyOneChild.meta?n("app-link",{attrs:{to:e.resolvePath(e.onlyOneChild.path)}},[n("el-menu-item",{class:{"submenu-title-noDropdown":!e.isNest},attrs:{index:e.resolvePath(e.onlyOneChild.path)}},[n("item",{attrs:{icon:e.onlyOneChild.meta.icon||e.item.meta&&e.item.meta.icon,title:e.onlyOneChild.meta.title}})],1)],1):e._e()]],2)},R=[],G=n("df7c"),U=n.n(G),V=n("61f7"),F={name:"MenuItem",functional:!0,props:{icon:{type:String,default:""},title:{type:String,default:""}},render:function(e,t){var n=t.props,a=n.icon,s=n.title,i=[];return a&&i.push(e("svg-icon",{attrs:{"icon-class":a}})),s&&i.push(e("span",{slot:"title"},[s])),i}},J=F,Y=Object(w["a"])(J,a,s,!1,null,null,null),K=Y.exports,W=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("component",e._b({},"component",e.linkProps(e.to),!1),[e._t("default")],2)},Q=[],X={props:{to:{type:String,required:!0}},methods:{linkProps:function(e){return Object(V["a"])(e)?{is:"a",href:e,target:"_blank",rel:"noopener"}:{is:"router-link",to:e}}}},Z=X,ee=Object(w["a"])(Z,W,Q,!1,null,null,null),te=ee.exports,ne={computed:{device:function(){return this.$store.state.app.device}},mounted:function(){this.fixBugIniOS()},methods:{fixBugIniOS:function(){var e=this,t=this.$refs.subMenu;if(t){var n=t.handleMouseleave;t.handleMouseleave=function(t){"mobile"!==e.device&&n(t)}}}}},ae={name:"SidebarItem",components:{Item:K,AppLink:te},mixins:[ne],props:{item:{type:Object,required:!0},isNest:{type:Boolean,default:!1},basePath:{type:String,default:""}},data:function(){return this.onlyOneChild=null,{}},methods:{hasOneShowingChild:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],n=arguments.length>1?arguments[1]:void 0,a=t.filter((function(t){return!t.hidden&&(e.onlyOneChild=t,!0)}));return 1===a.length||0===a.length&&(this.onlyOneChild=Object(f["a"])({},n,{path:"",noShowingChildren:!0}),!0)},resolvePath:function(e){return Object(V["a"])(e)?e:Object(V["a"])(this.basePath)?this.basePath:U.a.resolve(this.basePath,e)}}},se=ae,ie=Object(w["a"])(se,q,R,!1,null,null,null),re=ie.exports,oe=n("cf1e2"),ce=n.n(oe),ue={components:{SidebarItem:re,Logo:D},computed:Object(f["a"])({},Object(h["b"])(["sidebar"]),{routes:function(){return this.$router.options.routes},activeMenu:function(){var e=this.$route,t=e.meta,n=e.path;return t.activeMenu?t.activeMenu:n},showLogo:function(){return this.$store.state.settings.sidebarLogo},variables:function(){return ce.a},isCollapse:function(){return!this.sidebar.opened}})},de=ue,le=Object(w["a"])(de,L,$,!1,null,null,null),fe=le.exports,he=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("section",{staticClass:"app-main"},[n("transition",{attrs:{name:"fade-transform",mode:"out-in"}},[n("router-view",{key:e.key})],1)],1)},me=[],be={name:"AppMain",computed:{key:function(){return this.$route.path}}},pe=be,ve=(n("e4de"),n("028b"),Object(w["a"])(pe,he,me,!1,null,"64cf4d83",null)),ge=ve.exports,je=n("4360"),we=document,ke=we.body,ye=992,xe={watch:{$route:function(e){"mobile"===this.device&&this.sidebar.opened&&je["a"].dispatch("app/closeSideBar",{withoutAnimation:!1})}},beforeMount:function(){window.addEventListener("resize",this.$_resizeHandler)},beforeDestroy:function(){window.removeEventListener("resize",this.$_resizeHandler)},mounted:function(){var e=this.$_isMobile();e&&(je["a"].dispatch("app/toggleDevice","mobile"),je["a"].dispatch("app/closeSideBar",{withoutAnimation:!0}))},methods:{$_isMobile:function(){var e=ke.getBoundingClientRect();return e.width-1'});r.a.add(o);t["default"]=o},b775:function(e,t,n){"use strict";var a=n("bc3a"),s=n.n(a),i=n("5c96"),r=n("4360"),o=n("5f87"),c=s.a.create({baseURL:"",timeout:5e3});c.interceptors.request.use((function(e){return r["a"].getters.token&&(e.headers["Authorization"]="Bearer "+Object(o["a"])()),e}),(function(e){return console.log(e),Promise.reject(e)})),c.interceptors.response.use((function(e){var t=e.data;return 4999===t.code?(Object(i["Message"])({message:t.msg||"Error",type:"error",duration:5e3}),Promise.reject(new Error(t.message||"Error"))):t}),(function(e){var t=e.response;return 401===t.status?i["MessageBox"].confirm("你的登入已过期,请重新登入","登入过期",{confirmButtonText:"重新登入",cancelButtonText:"取消",type:"warning"}).then((function(){r["a"].dispatch("user/resetToken").then((function(){location.reload()}))})):500===t.status&&Object(i["Message"])({message:"服务器繁忙,请稍后再试...",type:"error",duration:5e3}),Promise.reject(e)})),t["a"]=c},bf90:function(e,t,n){},c24f:function(e,t,n){"use strict";n.d(t,"c",(function(){return s})),n.d(t,"b",(function(){return i})),n.d(t,"d",(function(){return r})),n.d(t,"a",(function(){return o}));var a=n("b775");function s(e){return Object(a["a"])({url:"/v1/user/login",method:"post",data:e})}function i(){return Object(a["a"])({url:"/v1/user/info",method:"get"})}function r(){return Object(a["a"])({url:"/v1/user/logout",method:"post"})}function o(e){return Object(a["a"])({url:"/v1/user/change-password",method:"patch",data:e})}},c2a3:function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-add",use:"icon-add-usage",viewBox:"0 0 1026 1024",content:''});r.a.add(o);t["default"]=o},cf1e2:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},d1a7:function(e,t,n){"use strict";var a=n("031b"),s=n.n(a);s.a},d7ec:function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-eye-open",use:"icon-eye-open-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(o);t["default"]=o},dc52:function(e,t,n){},e4de:function(e,t,n){"use strict";var a=n("8902"),s=n.n(a);s.a},eb1b:function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-form",use:"icon-form-usage",viewBox:"0 0 128 128",content:''});r.a.add(o);t["default"]=o},f12c:function(e,t,n){},f782:function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-dashboard",use:"icon-dashboard-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(o);t["default"]=o}},[[0,"runtime","chunk-elementUI","chunk-libs"]]]);
\ No newline at end of file
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["app"],{0:function(e,t,n){e.exports=n("56d7")},"028b":function(e,t,n){"use strict";var a=n("f12c"),s=n.n(a);s.a},"031b":function(e,t,n){},"186a":function(e,t,n){"use strict";var a=n("dc52"),s=n.n(a);s.a},"18f0":function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-link",use:"icon-link-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(o);t["default"]=o},2995:function(e,t,n){},"2a3d":function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-password",use:"icon-password-usage",viewBox:"0 0 128 128",content:''});r.a.add(o);t["default"]=o},3289:function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-list",use:"icon-list-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(o);t["default"]=o},"34c8":function(e,t,n){"use strict";var a=n("88a1"),s=n.n(a);s.a},4360:function(e,t,n){"use strict";var a=n("2b0e"),s=n("2f62"),i=(n("b54a"),n("7f7f"),{sidebar:function(e){return e.app.sidebar},device:function(e){return e.app.device},token:function(e){return e.user.token},name:function(e){return e.user.name},role:function(e){return e.user.role},pinned:function(e){return e.link.pinned}}),r=i,o=n("a78e"),c=n.n(o),u={sidebar:{opened:!c.a.get("sidebarStatus")||!!+c.a.get("sidebarStatus"),withoutAnimation:!1},device:"desktop"},d={TOGGLE_SIDEBAR:function(e){e.sidebar.opened=!e.sidebar.opened,e.sidebar.withoutAnimation=!1,e.sidebar.opened?c.a.set("sidebarStatus",1):c.a.set("sidebarStatus",0)},CLOSE_SIDEBAR:function(e,t){c.a.set("sidebarStatus",0),e.sidebar.opened=!1,e.sidebar.withoutAnimation=t},TOGGLE_DEVICE:function(e,t){e.device=t}},l={toggleSideBar:function(e){var t=e.commit;t("TOGGLE_SIDEBAR")},closeSideBar:function(e,t){var n=e.commit,a=t.withoutAnimation;n("CLOSE_SIDEBAR",a)},toggleDevice:function(e,t){var n=e.commit;n("TOGGLE_DEVICE",t)}},f={namespaced:!0,state:u,mutations:d,actions:l},m=n("83d6"),h=n.n(m),b=h.a.showSettings,p=h.a.fixedHeader,v=h.a.sidebarLogo,g={showSettings:b,fixedHeader:p,sidebarLogo:v},j={CHANGE_SETTING:function(e,t){var n=t.key,a=t.value;e.hasOwnProperty(n)&&(e[n]=a)}},w={changeSetting:function(e,t){var n=e.commit;n("CHANGE_SETTING",t)}},k={namespaced:!0,state:g,mutations:j,actions:w},y=n("c24f"),x=n("5f87"),_=n("a18c"),C=function(){return{token:Object(x["a"])(),name:"",role:1}},O=C(),z={RESET_STATE:function(e){Object.assign(e,C())},SET_TOKEN:function(e,t){e.token=t},SET_NAME:function(e,t){e.name=t},SET_ROLE:function(e,t){e.role=t}},S={login:function(e,t){var n=e.commit,a=t.username,s=t.password;return new Promise((function(e,t){Object(y["c"])({username:a.trim(),password:s}).then((function(t){var a=t.data;n("SET_TOKEN",a.token),Object(x["c"])(a.token),e()})).catch((function(e){t(e)}))}))},getInfo:function(e){var t=e.commit;e.state;return new Promise((function(e,n){Object(y["b"])().then((function(a){var s=a.data;s||n("登入信息验证失败,请重新登入");var i=s.username,r=s.role;t("SET_NAME",i),t("SET_ROLE",r),e(s)})).catch((function(e){n(e)}))}))},logout:function(e){var t=e.commit,n=e.state;return new Promise((function(e,a){Object(y["d"])(n.token).then((function(){Object(x["b"])(),Object(_["b"])(),t("RESET_STATE"),e()})).catch((function(e){a(e)}))}))},resetToken:function(e){var t=e.commit;return new Promise((function(e){Object(x["b"])(),t("RESET_STATE"),e()}))}},E={namespaced:!0,state:O,mutations:z,actions:S},M="pinned",B={pinned:JSON.parse(localStorage.getItem(M)||"[]")},T={PIN:function(e,t){e.pinned.push(t)},UNPIN:function(e,t){e.pinned.indexOf(t)>=0&&e.pinned.splice(e.pinned.indexOf(t),1)}},L={pin:function(e,t){var n=e.commit,a=e.state;n("PIN",t),localStorage.setItem(M,JSON.stringify(a.pinned))},unpin:function(e,t){var n=e.commit,a=e.state;n("UNPIN",t),localStorage.setItem(M,JSON.stringify(a.pinned))}},$={namespaced:!0,state:B,mutations:T,actions:L};a["default"].use(s["a"]);var A=new s["a"].Store({modules:{app:f,settings:k,user:E,link:$},getters:r});t["a"]=A},4678:function(e,t,n){var a={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-SG":"cdab","./en-SG.js":"cdab","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-nz":"6f50","./en-nz.js":"6f50","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf75","./tlh.js":"cf75","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-tw":"90ea","./zh-tw.js":"90ea"};function s(e){var t=i(e);return n(t)}function i(e){var t=a[e];if(!(t+1)){var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}return t}s.keys=function(){return Object.keys(a)},s.resolve=i,e.exports=s,s.id="4678"},"4cdc":function(e,t,n){},"4df5":function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-eye",use:"icon-eye-usage",viewBox:"0 0 128 64",content:''});r.a.add(o);t["default"]=o},"51ff":function(e,t,n){var a={"./add.svg":"c2a3","./dashboard.svg":"f782","./eye-open.svg":"d7ec","./eye.svg":"4df5","./form.svg":"eb1b","./github.svg":"558d","./link.svg":"18f0","./list.svg":"3289","./password.svg":"2a3d","./user.svg":"b3b5"};function s(e){var t=i(e);return n(t)}function i(e){var t=a[e];if(!(t+1)){var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}return t}s.keys=function(){return Object.keys(a)},s.resolve=i,e.exports=s,s.id="51ff"},"558d":function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-github",use:"icon-github-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(o);t["default"]=o},"56d7":function(e,t,n){"use strict";n.r(t);n("cadf"),n("551c"),n("f751"),n("097d");var a=n("2b0e"),s=n("c1df"),i=n.n(s),r=(n("f5df"),n("5c96")),o=n.n(r),c=(n("0fae"),n("b20f"),function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"app"}},[n("router-view")],1)}),u=[],d={name:"App"},l=d,f=n("2877"),m=Object(f["a"])(l,c,u,!1,null,null,null),h=m.exports,b=n("4360"),p=n("a18c"),v=(n("ac6a"),function(){var e=this,t=e.$createElement,n=e._self._c||t;return e.isExternal?n("div",e._g({staticClass:"svg-external-icon svg-icon",style:e.styleExternalIcon},e.$listeners)):n("svg",e._g({class:e.svgClass,attrs:{"aria-hidden":"true"}},e.$listeners),[n("use",{attrs:{href:e.iconName}})])}),g=[],j=n("61f7"),w={name:"SvgIcon",props:{iconClass:{type:String,required:!0},className:{type:String,default:""}},computed:{isExternal:function(){return Object(j["a"])(this.iconClass)},iconName:function(){return"#icon-".concat(this.iconClass)},svgClass:function(){return this.className?"svg-icon "+this.className:"svg-icon"},styleExternalIcon:function(){return{mask:"url(".concat(this.iconClass,") no-repeat 50% 50%"),"-webkit-mask":"url(".concat(this.iconClass,") no-repeat 50% 50%")}}}},k=w,y=(n("d1a7"),Object(f["a"])(k,v,g,!1,null,"4342976c",null)),x=y.exports;a["default"].component("svg-icon",x);var _=n("51ff"),C=function(e){return e.keys().map(e)};C(_);n("7f7f"),n("96cf");var O=n("3b8d"),z=n("323e"),S=n.n(z),E=(n("a5d8"),n("5f87")),M=n("83d6"),B=n.n(M),T=B.a.title||"Vue Admin Template";function L(e){return e?"".concat(e," - ").concat(T):"".concat(T)}S.a.configure({showSpinner:!1});var $=["/login"];p["a"].beforeEach(function(){var e=Object(O["a"])(regeneratorRuntime.mark((function e(t,n,a){var s,i;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:if(S.a.start(),document.title=L(t.meta.title),s=Object(E["a"])(),!s){e.next=29;break}if("/login"!==t.path){e.next=9;break}a({path:"/"}),S.a.done(),e.next=27;break;case 9:if(i=b["a"].getters.name,!i){e.next=14;break}a(),e.next=27;break;case 14:return e.prev=14,e.next=17,b["a"].dispatch("user/getInfo");case 17:a(),e.next=27;break;case 20:return e.prev=20,e.t0=e["catch"](14),e.next=24,b["a"].dispatch("user/resetToken");case 24:r["Message"].error(e.t0||"Has Error"),a("/login?redirect=".concat(t.path)),S.a.done();case 27:e.next=30;break;case 29:-1!==$.indexOf(t.path)?a():(a("/login?redirect=".concat(t.path)),S.a.done());case 30:case"end":return e.stop()}}),e,null,[[14,20]])})));return function(t,n,a){return e.apply(this,arguments)}}()),p["a"].afterEach((function(){S.a.done()})),a["default"].filter("dateformat",(function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"YYYY-MM-DD HH:mm:ss";return e?i()(e).format(t):"-"})),a["default"].use(o.a),a["default"].config.productionTip=!1,new a["default"]({el:"#app",router:p["a"],store:b["a"],render:function(e){return e(h)}})},"5f87":function(e,t,n){"use strict";n.d(t,"a",(function(){return r})),n.d(t,"c",(function(){return o})),n.d(t,"b",(function(){return c}));var a=n("a78e"),s=n.n(a),i="j2_token";function r(){return s.a.get(i)}function o(e){return s.a.set(i,e)}function c(){return s.a.remove(i)}},"61f7":function(e,t,n){"use strict";n.d(t,"a",(function(){return a})),n.d(t,"c",(function(){return s})),n.d(t,"b",(function(){return r}));n("3b2b");function a(e){return/^(https?:|mailto:|tel:)/.test(e)}function s(e){return e.length>=2}var i=new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|localhost|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\#[-a-z\\d_\\/]*)?(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$","i");function r(e){return!!i.test(e)}},"6b31":function(e,t,n){"use strict";var a=n("4cdc"),s=n.n(a);s.a},"83d6":function(e,t){e.exports={title:"Jump Jump Admin",fixedHeader:!1,sidebarLogo:!1}},"88a1":function(e,t,n){},8902:function(e,t,n){},"9f2b":function(e,t,n){"use strict";var a=n("bf90"),s=n.n(a);s.a},"9f43":function(e,t,n){"use strict";var a=n("2995"),s=n.n(a);s.a},a18c:function(e,t,n){"use strict";var a,s,i=n("2b0e"),r=n("8c4f"),o=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-wrapper",class:e.classObj},["mobile"===e.device&&e.sidebar.opened?n("div",{staticClass:"drawer-bg",on:{click:e.handleClickOutside}}):e._e(),e._v(" "),n("sidebar",{staticClass:"sidebar-container"}),e._v(" "),n("div",{staticClass:"main-container"},[n("div",{class:{"fixed-header":e.fixedHeader}},[n("navbar")],1),e._v(" "),n("app-main")],1)],1)},c=[],u=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"navbar"},[n("hamburger",{staticClass:"hamburger-container",attrs:{"is-active":e.sidebar.opened},on:{toggleClick:e.toggleSideBar}}),e._v(" "),n("breadcrumb",{staticClass:"breadcrumb-container"}),e._v(" "),n("div",{staticClass:"right-menu"},[n("el-dropdown",{staticClass:"username-container",attrs:{trigger:"click"}},[n("div",{staticClass:"username-wrapper"},[n("span",{staticStyle:{cursor:"pointer"}},[e._v(e._s(e.name))])]),e._v(" "),n("el-dropdown-menu",{staticClass:"user-dropdown",attrs:{slot:"dropdown"},slot:"dropdown"},[n("router-link",{attrs:{to:"/"}},[n("el-dropdown-item",[e._v("首页")])],1),e._v(" "),n("router-link",{attrs:{to:"/security/change-password"}},[n("el-dropdown-item",[e._v("修改密码")])],1),e._v(" "),n("a",{attrs:{target:"_blank",href:"https://github.com/jwma/jump-jump"}},[n("el-dropdown-item",[e._v("Github")])],1),e._v(" "),n("el-dropdown-item",{attrs:{divided:""},nativeOn:{click:function(t){return e.logout(t)}}},[n("span",{staticStyle:{display:"block"}},[e._v("登出")])])],1)],1)],1)],1)},d=[],l=(n("96cf"),n("3b8d")),f=n("db72"),m=n("2f62"),h=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("el-breadcrumb",{staticClass:"app-breadcrumb",attrs:{separator:"/"}},[n("transition-group",{attrs:{name:"breadcrumb"}},e._l(e.levelList,(function(t,a){return n("el-breadcrumb-item",{key:t.path},["noRedirect"===t.redirect||a==e.levelList.length-1?n("span",{staticClass:"no-redirect"},[e._v(e._s(t.meta.title))]):n("a",{on:{click:function(n){return n.preventDefault(),e.handleLink(t)}}},[e._v(e._s(t.meta.title))])])})),1)],1)},b=[],p=(n("7f7f"),n("bd11")),v=n.n(p),g={data:function(){return{levelList:null}},watch:{$route:function(){this.getBreadcrumb()}},created:function(){this.getBreadcrumb()},methods:{getBreadcrumb:function(){var e=this.$route.matched.filter((function(e){return e.meta&&e.meta.title})),t=e[0];this.isDashboard(t)||(e=[{path:"/dashboard",meta:{title:"Dashboard"}}].concat(e)),this.levelList=e.filter((function(e){return e.meta&&e.meta.title&&!1!==e.meta.breadcrumb}))},isDashboard:function(e){var t=e&&e.name;return!!t&&t.trim().toLocaleLowerCase()==="Dashboard".toLocaleLowerCase()},pathCompile:function(e){var t=this.$route.params,n=v.a.compile(e);return n(t)},handleLink:function(e){var t=e.redirect,n=e.path;t?this.$router.push(t):this.$router.push(this.pathCompile(n))}}},j=g,w=(n("34c8"),n("2877")),k=Object(w["a"])(j,h,b,!1,null,"62cc9144",null),y=k.exports,x=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticStyle:{padding:"0 15px"},on:{click:e.toggleClick}},[n("svg",{staticClass:"hamburger",class:{"is-active":e.isActive},attrs:{viewBox:"0 0 1024 1024",xmlns:"http://www.w3.org/2000/svg",width:"64",height:"64"}},[n("path",{attrs:{d:"M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"}})])])},_=[],C={name:"Hamburger",props:{isActive:{type:Boolean,default:!1}},methods:{toggleClick:function(){this.$emit("toggleClick")}}},O=C,z=(n("186a"),Object(w["a"])(O,x,_,!1,null,"49e15297",null)),S=z.exports,E={components:{Breadcrumb:y,Hamburger:S},computed:Object(f["a"])({},Object(m["b"])(["sidebar","name"])),methods:{toggleSideBar:function(){this.$store.dispatch("app/toggleSideBar")},logout:function(){var e=Object(l["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.next=2,this.$store.dispatch("user/logout");case 2:this.$router.push("/login?redirect=".concat(this.$route.fullPath));case 3:case"end":return e.stop()}}),e,this)})));function t(){return e.apply(this,arguments)}return t}()}},M=E,B=(n("9f43"),Object(w["a"])(M,u,d,!1,null,"26745010",null)),T=B.exports,L=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{class:{"has-logo":e.showLogo}},[e.showLogo?n("logo",{attrs:{collapse:e.isCollapse}}):e._e(),e._v(" "),n("el-scrollbar",{attrs:{"wrap-class":"scrollbar-wrapper"}},[n("el-menu",{attrs:{"default-active":e.activeMenu,collapse:e.isCollapse,"background-color":e.variables.menuBg,"text-color":e.variables.menuText,"unique-opened":!1,"active-text-color":e.variables.menuActiveText,"collapse-transition":!1,mode:"vertical"}},e._l(e.routes,(function(e){return n("sidebar-item",{key:e.path,attrs:{item:e,"base-path":e.path}})})),1)],1)],1)},$=[],A=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"sidebar-logo-container",class:{collapse:e.collapse}},[n("transition",{attrs:{name:"sidebarLogoFade"}},[e.collapse?n("router-link",{key:"collapse",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])]):n("router-link",{key:"expand",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):e._e(),e._v(" "),n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])])],1)],1)},H=[],N={name:"SidebarLogo",props:{collapse:{type:Boolean,required:!0}},data:function(){return{title:"Vue Admin Template",logo:"https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png"}}},I=N,P=(n("6b31"),Object(w["a"])(I,A,H,!1,null,"5bb1c0e2",null)),D=P.exports,q=function(){var e=this,t=e.$createElement,n=e._self._c||t;return e.item.hidden?e._e():n("div",[!e.hasOneShowingChild(e.item.children,e.item)||e.onlyOneChild.children&&!e.onlyOneChild.noShowingChildren||e.item.alwaysShow?n("el-submenu",{ref:"subMenu",attrs:{index:e.resolvePath(e.item.path),"popper-append-to-body":""}},[n("template",{slot:"title"},[e.item.meta?n("item",{attrs:{icon:e.item.meta&&e.item.meta.icon,title:e.item.meta.title}}):e._e()],1),e._v(" "),e._l(e.item.children,(function(t){return n("sidebar-item",{key:t.path,staticClass:"nest-menu",attrs:{"is-nest":!0,item:t,"base-path":e.resolvePath(t.path)}})}))],2):[e.onlyOneChild.meta?n("app-link",{attrs:{to:e.resolvePath(e.onlyOneChild.path)}},[n("el-menu-item",{class:{"submenu-title-noDropdown":!e.isNest},attrs:{index:e.resolvePath(e.onlyOneChild.path)}},[n("item",{attrs:{icon:e.onlyOneChild.meta.icon||e.item.meta&&e.item.meta.icon,title:e.onlyOneChild.meta.title}})],1)],1):e._e()]],2)},R=[],G=n("df7c"),U=n.n(G),V=n("61f7"),F={name:"MenuItem",functional:!0,props:{icon:{type:String,default:""},title:{type:String,default:""}},render:function(e,t){var n=t.props,a=n.icon,s=n.title,i=[];return a&&i.push(e("svg-icon",{attrs:{"icon-class":a}})),s&&i.push(e("span",{slot:"title"},[s])),i}},J=F,Y=Object(w["a"])(J,a,s,!1,null,null,null),K=Y.exports,W=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("component",e._b({},"component",e.linkProps(e.to),!1),[e._t("default")],2)},Q=[],X={props:{to:{type:String,required:!0}},methods:{linkProps:function(e){return Object(V["a"])(e)?{is:"a",href:e,target:"_blank",rel:"noopener"}:{is:"router-link",to:e}}}},Z=X,ee=Object(w["a"])(Z,W,Q,!1,null,null,null),te=ee.exports,ne={computed:{device:function(){return this.$store.state.app.device}},mounted:function(){this.fixBugIniOS()},methods:{fixBugIniOS:function(){var e=this,t=this.$refs.subMenu;if(t){var n=t.handleMouseleave;t.handleMouseleave=function(t){"mobile"!==e.device&&n(t)}}}}},ae={name:"SidebarItem",components:{Item:K,AppLink:te},mixins:[ne],props:{item:{type:Object,required:!0},isNest:{type:Boolean,default:!1},basePath:{type:String,default:""}},data:function(){return this.onlyOneChild=null,{}},methods:{hasOneShowingChild:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],n=arguments.length>1?arguments[1]:void 0,a=t.filter((function(t){return!t.hidden&&(e.onlyOneChild=t,!0)}));return 1===a.length||0===a.length&&(this.onlyOneChild=Object(f["a"])({},n,{path:"",noShowingChildren:!0}),!0)},resolvePath:function(e){return Object(V["a"])(e)?e:Object(V["a"])(this.basePath)?this.basePath:U.a.resolve(this.basePath,e)}}},se=ae,ie=Object(w["a"])(se,q,R,!1,null,null,null),re=ie.exports,oe=n("cf1e2"),ce=n.n(oe),ue={components:{SidebarItem:re,Logo:D},computed:Object(f["a"])({},Object(m["b"])(["sidebar"]),{routes:function(){return this.$router.options.routes},activeMenu:function(){var e=this.$route,t=e.meta,n=e.path;return t.activeMenu?t.activeMenu:n},showLogo:function(){return this.$store.state.settings.sidebarLogo},variables:function(){return ce.a},isCollapse:function(){return!this.sidebar.opened}})},de=ue,le=Object(w["a"])(de,L,$,!1,null,null,null),fe=le.exports,me=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("section",{staticClass:"app-main"},[n("transition",{attrs:{name:"fade-transform",mode:"out-in"}},[n("router-view",{key:e.key})],1)],1)},he=[],be={name:"AppMain",computed:{key:function(){return this.$route.path}}},pe=be,ve=(n("e4de"),n("028b"),Object(w["a"])(pe,me,he,!1,null,"64cf4d83",null)),ge=ve.exports,je=n("4360"),we=document,ke=we.body,ye=992,xe={watch:{$route:function(e){"mobile"===this.device&&this.sidebar.opened&&je["a"].dispatch("app/closeSideBar",{withoutAnimation:!1})}},beforeMount:function(){window.addEventListener("resize",this.$_resizeHandler)},beforeDestroy:function(){window.removeEventListener("resize",this.$_resizeHandler)},mounted:function(){var e=this.$_isMobile();e&&(je["a"].dispatch("app/toggleDevice","mobile"),je["a"].dispatch("app/closeSideBar",{withoutAnimation:!0}))},methods:{$_isMobile:function(){var e=ke.getBoundingClientRect();return e.width-1'});r.a.add(o);t["default"]=o},b775:function(e,t,n){"use strict";var a=n("bc3a"),s=n.n(a),i=n("5c96"),r=n("4360"),o=n("5f87"),c=s.a.create({baseURL:"",timeout:5e3});c.interceptors.request.use((function(e){return r["a"].getters.token&&(e.headers["Authorization"]="Bearer "+Object(o["a"])()),e}),(function(e){return console.log(e),Promise.reject(e)})),c.interceptors.response.use((function(e){var t=e.data;return 4999===t.code?(Object(i["Message"])({message:t.msg||"Error",type:"error",duration:5e3}),Promise.reject(new Error(t.message||"Error"))):t}),(function(e){var t=e.response;return 401===t.status?i["MessageBox"].confirm("你的登入已过期,请重新登入","登入过期",{confirmButtonText:"重新登入",cancelButtonText:"取消",type:"warning"}).then((function(){r["a"].dispatch("user/resetToken").then((function(){location.reload()}))})):500===t.status&&Object(i["Message"])({message:"服务器繁忙,请稍后再试...",type:"error",duration:5e3}),Promise.reject(e)})),t["a"]=c},bf90:function(e,t,n){},c24f:function(e,t,n){"use strict";n.d(t,"c",(function(){return s})),n.d(t,"b",(function(){return i})),n.d(t,"d",(function(){return r})),n.d(t,"a",(function(){return o}));var a=n("b775");function s(e){return Object(a["a"])({url:"/v1/user/login",method:"post",data:e})}function i(){return Object(a["a"])({url:"/v1/user/info",method:"get"})}function r(){return Object(a["a"])({url:"/v1/user/logout",method:"post"})}function o(e){return Object(a["a"])({url:"/v1/user/change-password",method:"post",data:e})}},c2a3:function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-add",use:"icon-add-usage",viewBox:"0 0 1026 1024",content:''});r.a.add(o);t["default"]=o},cf1e2:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},d1a7:function(e,t,n){"use strict";var a=n("031b"),s=n.n(a);s.a},d7ec:function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-eye-open",use:"icon-eye-open-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(o);t["default"]=o},dc52:function(e,t,n){},e4de:function(e,t,n){"use strict";var a=n("8902"),s=n.n(a);s.a},eb1b:function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-form",use:"icon-form-usage",viewBox:"0 0 128 128",content:''});r.a.add(o);t["default"]=o},f12c:function(e,t,n){},f782:function(e,t,n){"use strict";n.r(t);var a=n("e017"),s=n.n(a),i=n("21a1"),r=n.n(i),o=new s.a({id:"icon-dashboard",use:"icon-dashboard-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(o);t["default"]=o}},[[0,"runtime","chunk-elementUI","chunk-libs"]]]);
\ No newline at end of file
diff --git a/web/admin/static/js/chunk-13714370.65803237.js b/web/admin/static/js/chunk-13714370.65803237.js
new file mode 100644
index 0000000..ebbd013
--- /dev/null
+++ b/web/admin/static/js/chunk-13714370.65803237.js
@@ -0,0 +1,8 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-13714370"],{"80f1":function(e,t,r){},9472:function(e,t,r){"use strict";r.r(t);var n=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("el-main",[r("el-drawer",{ref:"createFormDrawer",attrs:{visible:e.createFormDrawer,direction:"rtl","before-close":e.handleCreateFormDrawerClose},on:{"update:visible":function(t){e.createFormDrawer=t}}},[r("div",{staticStyle:{width:"90%","margin-left":"15px"}},[r("h2",{staticStyle:{"margin-top":"0",color:"#606266"}},[e._v("添加短链接")]),e._v(" "),r("el-form",{ref:"createForm",attrs:{model:e.createForm,rules:e.createFormRules}},[r("el-form-item",{directives:[{name:"show",rawName:"v-show",value:2===e.role,expression:"role === 2"}],attrs:{label:"指定 ID",prop:"id"}},[r("el-switch",{on:{change:function(t){return e.specifyIdChange(t)}},model:{value:e.createForm.specifyId,callback:function(t){e.$set(e.createForm,"specifyId",t)},expression:"createForm.specifyId"}}),e._v(" "),r("el-popover",{attrs:{placement:"bottom",width:"320",trigger:"hover"}},[r("p",[e._v("设置你期望的ID,设置后随机ID将不起作用。")]),e._v(" "),r("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})]),e._v(" "),r("el-input",{directives:[{name:"show",rawName:"v-show",value:e.createForm.specifyId,expression:"createForm.specifyId"}],attrs:{disabled:e.createForm.setIdLength,placeholder:"示例:home"},model:{value:e.createForm.id,callback:function(t){e.$set(e.createForm,"id",t)},expression:"createForm.id"}})],1),e._v(" "),r("el-form-item",{directives:[{name:"show",rawName:"v-show",value:2===e.role,expression:"role === 2"}],attrs:{label:"指定随机 ID 长度",prop:"idLength"}},[r("el-switch",{on:{change:function(t){return e.setIdLengthChange(t)}},model:{value:e.createForm.setIdLength,callback:function(t){e.$set(e.createForm,"setIdLength",t)},expression:"createForm.setIdLength"}}),e._v(" "),r("el-popover",{attrs:{placement:"bottom",width:"320",trigger:"hover"}},[r("p",[e._v("在允许的范围内指定随机ID的长度,不指定时会使用系统默认设置。")]),e._v(" "),r("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})]),e._v(" "),r("el-slider",{directives:[{name:"show",rawName:"v-show",value:e.createForm.setIdLength,expression:"createForm.setIdLength"}],attrs:{"show-input":"",disabled:e.createForm.specifyId,min:e.idConfig.idMinimumLength,max:e.idConfig.idMaximumLength},model:{value:e.createForm.idLength,callback:function(t){e.$set(e.createForm,"idLength",t)},expression:"createForm.idLength"}})],1),e._v(" "),r("el-form-item",{attrs:{label:"目标链接",prop:"url"}},[r("el-input",{attrs:{placeholder:"示例:https://github.com/jwma/jump-jump"},model:{value:e.createForm.url,callback:function(t){e.$set(e.createForm,"url",t)},expression:"createForm.url"}})],1),e._v(" "),r("el-form-item",{attrs:{label:"描述",prop:"description"}},[r("el-input",{attrs:{type:"textarea",placeholder:"示例:某某帖子使用"},model:{value:e.createForm.description,callback:function(t){e.$set(e.createForm,"description",t)},expression:"createForm.description"}})],1),e._v(" "),r("el-form-item",{attrs:{label:"启用?",prop:"isEnable"}},[r("el-switch",{model:{value:e.createForm.isEnable,callback:function(t){e.$set(e.createForm,"isEnable",t)},expression:"createForm.isEnable"}}),e._v(" "),r("el-popover",{attrs:{placement:"bottom",width:"320",trigger:"hover"}},[r("p",[e._v("开启后短链接可以正常被访问,关闭后短链接被访问时会告知用户访问的页面不存在。"),r("br"),e._v(" "),r("strong",[e._v("注意:关闭后不会统计短链接访问的数据。")])]),e._v(" "),r("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})])],1),e._v(" "),r("el-form-item",[r("el-button",{attrs:{size:"mini",type:"primary"},on:{click:e.onCreateFormSubmit}},[e._v("添加")]),e._v(" "),r("el-button",{attrs:{size:"mini"},on:{click:e.onCreateFormCancel}},[e._v("取消")])],1)],1)],1)]),e._v(" "),r("el-drawer",{ref:"editFormDrawer",attrs:{visible:e.editFormDrawer,direction:"rtl","before-close":e.handleEditFormDrawerClose},on:{"update:visible":function(t){e.editFormDrawer=t}}},[r("div",{staticStyle:{width:"90%","margin-left":"15px"}},[r("h2",{staticStyle:{"margin-top":"0",color:"#606266"}},[e._v("更新:"+e._s(e.editForm.id))]),e._v(" "),r("el-form",{ref:"editForm",attrs:{model:e.editForm,rules:e.editFormRules}},[r("el-form-item",{attrs:{label:"目标链接",prop:"url"}},[r("el-input",{attrs:{placeholder:"示例:https://github.com/jwma/jump-jump"},model:{value:e.editForm.url,callback:function(t){e.$set(e.editForm,"url",t)},expression:"editForm.url"}})],1),e._v(" "),r("el-form-item",{attrs:{label:"描述",prop:"description"}},[r("el-input",{attrs:{type:"textarea",placeholder:"示例:某某帖子使用"},model:{value:e.editForm.description,callback:function(t){e.$set(e.editForm,"description",t)},expression:"editForm.description"}})],1),e._v(" "),r("el-form-item",{attrs:{label:"启用?",prop:"isEnable"}},[r("el-switch",{model:{value:e.editForm.isEnable,callback:function(t){e.$set(e.editForm,"isEnable",t)},expression:"editForm.isEnable"}}),e._v(" "),r("el-popover",{attrs:{placement:"bottom",width:"320",trigger:"hover"}},[r("p",[e._v("开启后短链接可以正常被访问,关闭后短链接被访问时会告知用户访问的页面不存在。"),r("br"),e._v(" "),r("strong",[e._v("注意:关闭后不会统计短链接访问的数据。")])]),e._v(" "),r("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})])],1),e._v(" "),r("el-form-item",{attrs:{label:"创建人"}},[r("span",{staticStyle:{color:"#909399"}},[e._v(e._s(e.editForm.createdBy))])]),e._v(" "),r("el-form-item",{attrs:{label:"添加时间"}},[r("span",{staticStyle:{color:"#909399"}},[e._v(e._s(e._f("dateformat")(e.editForm.createTime)))])]),e._v(" "),r("el-form-item",{attrs:{label:"更新时间"}},[r("span",{staticStyle:{color:"#909399"}},[e._v(e._s(e._f("dateformat")(e.editForm.updateTime)))])]),e._v(" "),r("el-form-item",[r("el-button",{attrs:{size:"mini",type:"primary"},on:{click:e.onEditFormSubmit}},[e._v("更新")]),e._v(" "),r("el-button",{attrs:{size:"mini"},on:{click:e.onEditFormCancel}},[e._v("取消")])],1)],1)],1)]),e._v(" "),r("el-button",{attrs:{icon:"el-icon-refresh",size:"mini"},on:{click:function(t){return e.getList(e.currentPage)}}},[e._v("刷新")]),e._v(" "),r("el-button",{attrs:{icon:"el-icon-plus",size:"mini",type:"primary"},on:{click:function(t){return e.toCreate()}}},[e._v("添加\n ")]),e._v(" "),r("el-table",{staticStyle:{width:"100%"},attrs:{data:e.list,"max-height":"800",fit:""}},[r("el-table-column",{attrs:{label:"短链接",width:"250"},scopedSlots:e._u([{key:"default",fn:function(t){return[r("i",{class:{"el-icon-star-off":-1==e.pinned.indexOf(t.row.id),"el-icon-star-on":-1!=e.pinned.indexOf(t.row.id)},staticStyle:{cursor:"pointer"},on:{click:function(r){return e.pin(t.row.id)}}}),e._v(" "),r("el-dropdown",{attrs:{size:"small"}},[r("span",{staticClass:"el-dropdown-link",staticStyle:{cursor:"pointer"}},[e._v("\n "+e._s(t.row.id)),r("i",{staticClass:"el-icon-arrow-down el-icon--right"})]),e._v(" "),r("el-dropdown-menu",{attrs:{slot:"dropdown"},slot:"dropdown"},e._l(e.landingHosts,(function(n){return r("el-dropdown-item",[r("span",{on:{click:function(r){return e.copyShortLink(n+t.row.id,r)}}},[e._v(e._s(n+t.row.id))])])})),1)],1)]}}])}),e._v(" "),r("el-table-column",{attrs:{prop:"url",label:"目标链接",width:"250"},scopedSlots:e._u([{key:"default",fn:function(t){return[r("el-dropdown",{attrs:{size:"small"}},[r("span",{staticClass:"el-dropdown-link",staticStyle:{cursor:"pointer"}},[r("span",{staticStyle:{width:"200px",overflow:"hidden","text-overflow":"ellipsis","white-space":"nowrap",display:"inline-block"}},[e._v(e._s(t.row.url))])]),e._v(" "),r("el-dropdown-menu",{attrs:{slot:"dropdown"},slot:"dropdown"},[r("el-dropdown-item",{staticStyle:{"line-height":"18px"}},[r("span",{on:{click:function(r){return e.copyShortLink(t.row.url,r)}}},[e._v(e._s(t.row.url))])])],1)],1)]}}])}),e._v(" "),r("el-table-column",{attrs:{label:"描述",width:"300"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.description?t.row.description:"-")+"\n ")]}}])}),e._v(" "),r("el-table-column",{attrs:{label:"启用?",width:"70",align:"center"},scopedSlots:e._u([{key:"default",fn:function(e){return[r("i",{class:{"el-icon-check":e.row.isEnable,"el-icon-close":!e.row.isEnable}})]}}])}),e._v(" "),r("el-table-column",{attrs:{label:"创建人",width:"150",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.createdBy)+"\n ")]}}])}),e._v(" "),r("el-table-column",{attrs:{label:"添加时间",width:"100"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(e._f("dateformat")(t.row.createTime,"DD/MM/YY"))+"\n ")]}}])}),e._v(" "),r("el-table-column",{attrs:{label:"更新时间",width:"100"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(e._f("dateformat")(t.row.updateTime,"DD/MM/YY"))+"\n ")]}}])}),e._v(" "),r("el-table-column",{attrs:{label:"操作"},scopedSlots:e._u([{key:"default",fn:function(t){return[r("el-button",{attrs:{size:"mini",circle:"",icon:"el-icon-s-data"},on:{click:function(r){return e.goto({name:"ShortLinkData",params:{id:t.row.id}})}}}),e._v(" "),r("el-button",{attrs:{size:"mini",circle:"",icon:"el-icon-edit-outline"},on:{click:function(r){return e.toEdit(t.row.id)}}}),e._v(" "),r("el-button",{attrs:{type:"danger",size:"mini",icon:"el-icon-delete-solid",circle:""},on:{click:function(r){return e.deleteShortLink(t.row.id)}}})]}}])})],1),e._v(" "),r("div",{staticClass:"paginator-container"},[r("el-pagination",{attrs:{"current-page":e.currentPage,"page-sizes":[10,20,30],"page-size":e.pageSize,layout:"total, sizes, prev, pager, next, jumper",total:e.total},on:{"size-change":e.handlePageSizeChange,"current-change":e.handleCurrentPageChange}})],1)],1)},i=[],o=r("db72"),a=r("bfad"),c=r("da71"),s=r("61f7"),l=r("2b0e"),u=r("b311"),d=r.n(u);function f(){l["default"].prototype.$message({message:"复制成功",type:"success",duration:1500})}function m(){l["default"].prototype.$message({message:"复制失败",type:"error"})}function h(e,t){var r=new d.a(t.target,{text:function(){return e}});r.on("success",(function(){f(),r.off("error"),r.off("success"),r.destroy()})),r.on("error",(function(){m(),r.off("error"),r.off("success"),r.destroy()})),r.onClick(t)}var p=r("2f62"),g={name:"ShortLinkList",data:function(){var e=function(e,t,r){""!==t?r():r(new Error("请输入目标链接"))};return{landingHosts:[],list:[],total:0,currentPage:1,pageSize:20,createFormDrawer:!1,idConfig:{idMinimumLength:0,idLength:0,idMaximumLength:0},createForm:{specifyId:!1,setIdLength:!1,id:"",url:"",description:"",isEnable:!1,idLength:0},createFormRules:{url:[{required:!0,validator:e,trigger:"blur"}]},editFormDrawer:!1,editForm:{id:"",url:"",description:"",isEnable:!1,createdBy:"",createTime:"",updateTime:""},editFormRules:{url:[{validator:e,trigger:"blur"}]}}},beforeRouteUpdate:function(e,t,r){this.currentPage=e.query.page||this.currentPage,this.pageSize=e.query.pageSize||this.pageSize,this.getList(this.currentPage),r()},created:function(){var e=this;this.currentPage=parseInt(this.$route.query.page)||this.currentPage,this.pageSize=parseInt(this.$route.query.pageSize)||this.pageSize,Object(c["a"])().then((function(t){e.landingHosts=t.data.config.landingHosts,e.idConfig=t.data.config.idConfig,e.createForm.idLength=e.idConfig.idLength,e.getList(e.currentPage)}))},computed:Object(o["a"])({},Object(p["b"])(["role","pinned"])),methods:{goto:function(e){this.$router.push(e)},copyShortLink:function(e,t){h(e,t)},getList:function(e){var t=this;Object(a["b"])(e,this.pageSize).then((function(r){t.currentPage=e,t.total=r.data.total,t.list=r.data.shortLinks,1!==t.currentPage&&0===t.list.length&&t.total>0&&(t.currentPage=1,t.getList(1))}))},resetCreateForm:function(){this.createForm.specifyId=!1,this.createForm.setIdLength=!1,this.createForm.id="",this.createForm.url="",this.createForm.description="",this.createForm.isEnable=!1},resetEditForm:function(){this.editForm.url="",this.editForm.description="",this.editForm.isEnable=!1,this.editForm.createdBy="",this.editForm.createTime="",this.editForm.updateTime=""},getInvalidUrlTipsText:function(e){return'
目标链接不是常规的URL,确定继续?")},handlePageSizeChange:function(e){this.pageSize=e,this.currentPage=1,this.$router.push({name:"ShortLinkList",query:{page:1,pageSize:e}})},handleCurrentPageChange:function(e){this.currentPage=e,this.$router.push({name:"ShortLinkList",query:{page:e,pageSize:this.pageSize}})},toCreate:function(){var e=this;Object(c["a"])().then((function(t){e.idConfig=t.data.config.idConfig,e.createForm.idLength=e.idConfig.idLength,e.createFormDrawer=!0}))},handleCreateFormDrawerClose:function(e){this.resetCreateForm(),e()},submitCreateForm:function(){var e=this;Object(a["a"])(this.createForm).then((function(t){e.$refs.createFormDrawer.closeDrawer(),e.$notify({title:"添加短链接成功",message:"ID:"+t.data.shortLink.id,type:"success"}),e.getList(e.currentPage)}))},onCreateFormSubmit:function(){var e=this;this.$refs.createForm.validate((function(t){if(!t)return!1;Object(s["b"])(e.createForm.url)?e.submitCreateForm():e.$confirm(e.getInvalidUrlTipsText(e.createForm.url),"提示",{confirmButtonText:"确定",cancelButtonText:"再改改",type:"warning",dangerouslyUseHTMLString:!0}).then((function(){e.submitCreateForm()}))}))},onCreateFormCancel:function(){this.resetCreateForm(),this.createFormDrawer=!1},toEdit:function(e){var t=this;Object(a["c"])(e).then((function(e){t.editFormDrawer=!0,t.editForm=e.data.shortLink}))},handleEditFormDrawerClose:function(e){this.resetEditForm(),e()},submitEditForm:function(){var e=this;Object(a["f"])(this.editForm.id,this.editForm).then((function(t){e.$refs.editFormDrawer.closeDrawer(),e.$notify({title:"更新成功",message:"ID:"+t.data.shortLink.id,type:"success"}),e.getList(e.currentPage)}))},onEditFormSubmit:function(){var e=this;this.$refs.editForm.validate((function(t){if(!t)return!1;Object(s["b"])(e.editForm.url)?e.submitEditForm():e.$confirm(e.getInvalidUrlTipsText(e.editForm.url),"提示",{confirmButtonText:"确定",cancelButtonText:"再改改",type:"warning",dangerouslyUseHTMLString:!0}).then((function(){e.submitEditForm()}))}))},onEditFormCancel:function(){this.resetEditForm(),this.editFormDrawer=!1},deleteShortLink:function(e){var t=this;this.$confirm("此操作会永久删除短链接,是否继续?","删除确认",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then((function(){Object(a["e"])(e).then((function(r){t.$notify({title:"成功删除短链接",message:"ID:".concat(e),type:"success"}),t.getList(t.currentPage),t.$store.dispatch("link/unpin",e)}))}))},specifyIdChange:function(e){e?(this.createForm.setIdLength=!1,this.setIdLengthChange(!1)):this.createForm.id=""},setIdLengthChange:function(e){e?(this.createForm.specifyId=!1,this.specifyIdChange(!1)):this.createForm.idLength=this.idConfig.idLength},pin:function(e){-1==this.pinned.indexOf(e)?(this.$store.dispatch("link/pin",e),this.$message({showClose:!0,type:"success",message:"Pin ".concat(e)})):(this.$store.dispatch("link/unpin",e),this.$message({showClose:!0,type:"success",message:"Unpin ".concat(e)}))}}},v=g,b=(r("e160"),r("2877")),y=Object(b["a"])(v,n,i,!1,null,"901f7d5c",null);t["default"]=y.exports},b311:function(e,t,r){
+/*!
+ * clipboard.js v2.0.6
+ * https://clipboardjs.com/
+ *
+ * Licensed MIT © Zeno Rocha
+ */
+(function(t,r){e.exports=r()})(0,(function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=6)}([function(e,t){function r(e){var t;if("SELECT"===e.nodeName)e.focus(),t=e.value;else if("INPUT"===e.nodeName||"TEXTAREA"===e.nodeName){var r=e.hasAttribute("readonly");r||e.setAttribute("readonly",""),e.select(),e.setSelectionRange(0,e.value.length),r||e.removeAttribute("readonly"),t=e.value}else{e.hasAttribute("contenteditable")&&e.focus();var n=window.getSelection(),i=document.createRange();i.selectNodeContents(e),n.removeAllRanges(),n.addRange(i),t=n.toString()}return t}e.exports=r},function(e,t){function r(){}r.prototype={on:function(e,t,r){var n=this.e||(this.e={});return(n[e]||(n[e]=[])).push({fn:t,ctx:r}),this},once:function(e,t,r){var n=this;function i(){n.off(e,i),t.apply(r,arguments)}return i._=t,this.on(e,i,r)},emit:function(e){var t=[].slice.call(arguments,1),r=((this.e||(this.e={}))[e]||[]).slice(),n=0,i=r.length;for(n;n0&&void 0!==arguments[0]?arguments[0]:{};this.action=e.action,this.container=e.container,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""}},{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var e=this,t="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return e.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[t?"right":"left"]="-9999px";var r=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=r+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=i()(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=i()(this.target),this.copyText()}},{key:"copyText",value:function(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function(e){this.emitter.emit(e?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),document.activeElement.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(e){if(void 0!==e){if(!e||"object"!==("undefined"===typeof e?"undefined":o(e))||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=e}},get:function(){return this._target}}]),e}(),l=s,u=r(1),d=r.n(u),f=r(2),m=r.n(f),h="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"===typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},p=function(){function e(e,t){for(var r=0;r0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"===typeof e.action?e.action:this.defaultAction,this.target="function"===typeof e.target?e.target:this.defaultTarget,this.text="function"===typeof e.text?e.text:this.defaultText,this.container="object"===h(e.container)?e.container:document.body}},{key:"listenClick",value:function(e){var t=this;this.listener=m()(e,"click",(function(e){return t.onClick(e)}))}},{key:"onClick",value:function(e){var t=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new l({action:this.action(t),target:this.target(t),text:this.text(t),container:this.container,trigger:t,emitter:this})}},{key:"defaultAction",value:function(e){return w("action",e)}},{key:"defaultTarget",value:function(e){var t=w("target",e);if(t)return document.querySelector(t)}},{key:"defaultText",value:function(e){return w("text",e)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],t="string"===typeof e?[e]:e,r=!!document.queryCommandSupported;return t.forEach((function(e){r=r&&!!document.queryCommandSupported(e)})),r}}]),t}(d.a);function w(e,t){var r="data-clipboard-"+e;if(t.hasAttribute(r))return t.getAttribute(r)}t["default"]=y}])["default"]}))},bfad:function(e,t,r){"use strict";r.d(t,"c",(function(){return i})),r.d(t,"b",(function(){return o})),r.d(t,"a",(function(){return a})),r.d(t,"e",(function(){return c})),r.d(t,"f",(function(){return s})),r.d(t,"d",(function(){return l}));var n=r("b775");function i(e){return Object(n["a"])({url:"/v1/short-link/".concat(e),method:"get"})}function o(e,t){return Object(n["a"])({url:"/v1/short-link/?page=".concat(e,"&pageSize=").concat(t),method:"get"})}function a(e){return Object(n["a"])({url:"/v1/short-link/",method:"post",data:e})}function c(e){return Object(n["a"])({url:"/v1/short-link/".concat(e),method:"delete"})}function s(e,t){return Object(n["a"])({url:"/v1/short-link/".concat(e),method:"patch",data:t})}function l(e,t,r){return Object(n["a"])({url:"/v1/short-link/".concat(e,"/data?startDate=").concat(t,"&endDate=").concat(r),method:"get"})}},da71:function(e,t,r){"use strict";r.d(t,"a",(function(){return i})),r.d(t,"c",(function(){return o})),r.d(t,"b",(function(){return a})),r.d(t,"d",(function(){return c}));var n=r("b775");function i(){return Object(n["a"])({url:"/v1/config",method:"get"})}function o(e){return Object(n["a"])({url:"/v1/config/landing-hosts",method:"patch",data:e})}function a(e){return Object(n["a"])({url:"/v1/config/id-length",method:"patch",data:e})}function c(e){return Object(n["a"])({url:"/v1/config/short-link-404-handling",method:"patch",data:e})}},e160:function(e,t,r){"use strict";var n=r("80f1"),i=r.n(n);i.a}}]);
\ No newline at end of file
diff --git a/web/admin/static/js/chunk-5011652c.8ca5679a.js b/web/admin/static/js/chunk-5011652c.8ca5679a.js
new file mode 100644
index 0000000..9732cfc
--- /dev/null
+++ b/web/admin/static/js/chunk-5011652c.8ca5679a.js
@@ -0,0 +1 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-5011652c"],{"14c9":function(t,a,e){"use strict";var n=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{class:t.className,style:{height:t.height,width:t.width}})},i=[],r=e("313e"),o=e.n(r);e("817d");var c={props:{className:{type:String,default:"chart"},width:{type:String,default:"100%"},height:{type:String,default:"350px"},autoResize:{type:Boolean,default:!0},chartData:{type:Object,required:!0},title:{type:Object,default:{}}},data:function(){return{chart:null}},watch:{chartData:{deep:!0,handler:function(t){this.setOptions(t)}}},mounted:function(){var t=this;this.$nextTick((function(){t.initChart()}))},beforeDestroy:function(){this.chart&&(this.chart.dispose(),this.chart=null)},methods:{initChart:function(){this.chart=o.a.init(this.$el,"macarons"),this.setOptions(this.chartData)},setOptions:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},a=t.pv,e=t.uv,n=t.dates;this.chart&&this.chart.setOption({title:this.title,xAxis:{data:n,boundaryGap:!1,axisTick:{show:!1}},grid:{left:50,right:50,bottom:20,top:30,containLabel:!0},tooltip:{trigger:"axis",axisPointer:{type:"cross"},padding:[5,10]},yAxis:{axisTick:{show:!1}},legend:{data:["PV","UV"]},series:[{name:"PV",itemStyle:{normal:{color:"#FF005A",lineStyle:{color:"#FF005A",width:2}}},smooth:!0,type:"line",data:a,animationDuration:2800,animationEasing:"cubicInOut"},{name:"UV",smooth:!0,type:"line",itemStyle:{normal:{color:"#3888fa",lineStyle:{color:"#3888fa",width:2},areaStyle:{color:"#f3f8ff"}}},data:e,animationDuration:2800,animationEasing:"quadraticOut"}]})}}},s=c,l=e("2877"),u=Object(l["a"])(s,n,i,!1,null,null,null);a["a"]=u.exports},bfad:function(t,a,e){"use strict";e.d(a,"c",(function(){return i})),e.d(a,"b",(function(){return r})),e.d(a,"a",(function(){return o})),e.d(a,"e",(function(){return c})),e.d(a,"f",(function(){return s})),e.d(a,"d",(function(){return l}));var n=e("b775");function i(t){return Object(n["a"])({url:"/v1/short-link/".concat(t),method:"get"})}function r(t,a){return Object(n["a"])({url:"/v1/short-link/?page=".concat(t,"&pageSize=").concat(a),method:"get"})}function o(t){return Object(n["a"])({url:"/v1/short-link/",method:"post",data:t})}function c(t){return Object(n["a"])({url:"/v1/short-link/".concat(t),method:"delete"})}function s(t,a){return Object(n["a"])({url:"/v1/short-link/".concat(t),method:"patch",data:a})}function l(t,a,e){return Object(n["a"])({url:"/v1/short-link/".concat(t,"/data?startDate=").concat(a,"&endDate=").concat(e),method:"get"})}},c3cc:function(t,a,e){"use strict";e.d(a,"b",(function(){return r})),e.d(a,"a",(function(){return o}));e("ac6a");var n=e("c1df"),i=e.n(n);function r(t){var a=i()(),e=a.clone().add(-(t-1),"d"),n=a.clone(),r=e.clone(),o=[];while(r.isSameOrBefore(n))o.push(r.format("YYYY-MM-DD")),r.add(1,"d");return{startDate:e,endDate:n,dates:o}}function o(t,a){var e={};t.forEach((function(t){e[t]={pv:0,ips:[]}})),a.forEach((function(t,a){var n=i()(t.time).format("YYYY-MM-DD");e[n].pv+=1,-1===e[n].ips.indexOf(t.ip)&&e[n].ips.push(t.ip)}));var n=[],r=[];return t.forEach((function(t){n.push(e[t].pv),r.push(e[t].ips.length)})),{pv:n,uv:r}}},df03:function(t,a,e){"use strict";e.r(a);var n=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("el-main",{staticStyle:{"margin-top":"5px","background-color":"rgb(240, 242, 245)",position:"relative"}},[e("el-page-header",{attrs:{content:t.title},on:{back:t.back}}),t._v(" "),e("el-divider"),t._v(" "),e("h3",{staticStyle:{color:"#555"}},[t._v("点击量/点击人数")]),t._v(" "),e("div",{staticStyle:{width:"100%","background-color":"#fff","padding-top":"15px"}},[e("line-chart",{attrs:{"chart-data":t.chartData.PvUv,height:"300px",title:{}}})],1),t._v(" "),e("el-divider"),t._v(" "),e("h3",{staticStyle:{color:"#555"}},[t._v("访问记录")]),t._v(" "),e("el-table",{attrs:{data:t.list,size:"mini"}},[e("el-table-column",{attrs:{prop:"url",label:"目标链接",width:"300"},scopedSlots:t._u([{key:"default",fn:function(a){return[e("el-link",{attrs:{type:"info",href:a.row.url,target:"_blank"}},[t._v(t._s(a.row.url))])]}}])}),t._v(" "),e("el-table-column",{attrs:{prop:"ip",label:"IP",width:"200"}}),t._v(" "),e("el-table-column",{attrs:{prop:"ua",label:"User Agent"}}),t._v(" "),e("el-table-column",{attrs:{label:"访问时间"},scopedSlots:t._u([{key:"default",fn:function(a){return[t._v("\n "+t._s(t._f("dateformat")(a.row.time))+"\n ")]}}])})],1)],1)},i=[],r=e("bfad"),o=e("14c9"),c=e("c3cc"),s={name:"ShortLinkData",components:{LineChart:o["a"]},data:function(){return{title:"",list:[],chartData:{PvUv:{pv:[],uv:[],dates:[]}},startDate:null,endDate:null}},created:function(){var t=Object(c["b"])(7);this.chartData.PvUv.dates=t.dates,this.getRequestHistoriesByDateRange(this.$route.params.id,t.startDate.format("YYYY-MM-DD"),t.endDate.format("YYYY-MM-DD"))},methods:{getRequestHistoriesByDateRange:function(t,a,e){var n=this;Object(r["d"])(t,a,e).then((function(t){n.list=t.data.histories;var a=Object(c["a"])(n.chartData.PvUv.dates,t.data.histories);n.chartData.PvUv.pv=a.pv,n.chartData.PvUv.uv=a.uv}))},back:function(){this.$router.go(-1)}}},l=s,u=e("2877"),d=Object(u["a"])(l,n,i,!1,null,"f0932b08",null);a["default"]=d.exports}}]);
\ No newline at end of file
diff --git a/web/admin/static/js/chunk-5011652c.b44c15c9.js b/web/admin/static/js/chunk-5011652c.b44c15c9.js
deleted file mode 100644
index 24a2807..0000000
--- a/web/admin/static/js/chunk-5011652c.b44c15c9.js
+++ /dev/null
@@ -1 +0,0 @@
-(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-5011652c"],{"14c9":function(t,e,a){"use strict";var n=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{class:t.className,style:{height:t.height,width:t.width}})},i=[],r=a("313e"),o=a.n(r);a("817d");var c={props:{className:{type:String,default:"chart"},width:{type:String,default:"100%"},height:{type:String,default:"350px"},autoResize:{type:Boolean,default:!0},chartData:{type:Object,required:!0},title:{type:Object,default:{}}},data:function(){return{chart:null}},watch:{chartData:{deep:!0,handler:function(t){this.setOptions(t)}}},mounted:function(){var t=this;this.$nextTick((function(){t.initChart()}))},beforeDestroy:function(){this.chart&&(this.chart.dispose(),this.chart=null)},methods:{initChart:function(){this.chart=o.a.init(this.$el,"macarons"),this.setOptions(this.chartData)},setOptions:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.pv,a=t.uv,n=t.dates;this.chart&&this.chart.setOption({title:this.title,xAxis:{data:n,boundaryGap:!1,axisTick:{show:!1}},grid:{left:50,right:50,bottom:20,top:30,containLabel:!0},tooltip:{trigger:"axis",axisPointer:{type:"cross"},padding:[5,10]},yAxis:{axisTick:{show:!1}},legend:{data:["PV","UV"]},series:[{name:"PV",itemStyle:{normal:{color:"#FF005A",lineStyle:{color:"#FF005A",width:2}}},smooth:!0,type:"line",data:e,animationDuration:2800,animationEasing:"cubicInOut"},{name:"UV",smooth:!0,type:"line",itemStyle:{normal:{color:"#3888fa",lineStyle:{color:"#3888fa",width:2},areaStyle:{color:"#f3f8ff"}}},data:a,animationDuration:2800,animationEasing:"quadraticOut"}]})}}},s=c,l=a("2877"),u=Object(l["a"])(s,n,i,!1,null,null,null);e["a"]=u.exports},bfad:function(t,e,a){"use strict";a.d(e,"d",(function(){return i})),a.d(e,"c",(function(){return r})),a.d(e,"a",(function(){return o})),a.d(e,"f",(function(){return c})),a.d(e,"g",(function(){return s})),a.d(e,"b",(function(){return l})),a.d(e,"e",(function(){return u}));var n=a("b775");function i(t){return Object(n["a"])({url:"/v1/short-link/".concat(t),method:"get"})}function r(t,e){return Object(n["a"])({url:"/v1/short-link/?page=".concat(t,"&pageSize=").concat(e),method:"get"})}function o(t){return Object(n["a"])({url:"/v1/short-link/",method:"post",data:t})}function c(t){return Object(n["a"])({url:"/v1/short-link/".concat(t),method:"delete"})}function s(t,e){return Object(n["a"])({url:"/v1/short-link/".concat(t),method:"patch",data:e})}function l(t,e){return Object(n["a"])({url:"/v1/short-link/".concat(t,"/latest-request-history?size=").concat(e),method:"get"})}function u(t,e,a){return Object(n["a"])({url:"/v1/short-link/".concat(t,"/data?startDate=").concat(e,"&endDate=").concat(a),method:"get"})}},c3cc:function(t,e,a){"use strict";a.d(e,"b",(function(){return r})),a.d(e,"a",(function(){return o}));a("ac6a");var n=a("c1df"),i=a.n(n);function r(t){var e=i()(),a=e.clone().add(-(t-1),"d"),n=e.clone(),r=a.clone(),o=[];while(r.isSameOrBefore(n))o.push(r.format("YYYY-MM-DD")),r.add(1,"d");return{startDate:a,endDate:n,dates:o}}function o(t,e){var a={};t.forEach((function(t){a[t]={pv:0,ips:[]}})),e.forEach((function(t,e){var n=i()(t.time).format("YYYY-MM-DD");a[n].pv+=1,-1===a[n].ips.indexOf(t.ip)&&a[n].ips.push(t.ip)}));var n=[],r=[];return t.forEach((function(t){n.push(a[t].pv),r.push(a[t].ips.length)})),{pv:n,uv:r}}},df03:function(t,e,a){"use strict";a.r(e);var n=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("el-main",{staticStyle:{"margin-top":"5px","background-color":"rgb(240, 242, 245)",position:"relative"}},[a("el-page-header",{attrs:{content:t.title},on:{back:t.back}}),t._v(" "),a("el-divider"),t._v(" "),a("h3",{staticStyle:{color:"#555"}},[t._v("点击量/点击人数")]),t._v(" "),a("div",{staticStyle:{width:"100%","background-color":"#fff","padding-top":"15px"}},[a("line-chart",{attrs:{"chart-data":t.chartData.PvUv,height:"300px"}})],1),t._v(" "),a("el-divider"),t._v(" "),a("h3",{staticStyle:{color:"#555"}},[t._v("访问记录")]),t._v(" "),a("el-table",{attrs:{data:t.list,size:"mini"}},[a("el-table-column",{attrs:{prop:"url",label:"目标链接",width:"300"},scopedSlots:t._u([{key:"default",fn:function(e){return[a("el-link",{attrs:{type:"info",href:e.row.url,target:"_blank"}},[t._v(t._s(e.row.url))])]}}])}),t._v(" "),a("el-table-column",{attrs:{prop:"ip",label:"IP",width:"200"}}),t._v(" "),a("el-table-column",{attrs:{prop:"ua",label:"User Agent"}}),t._v(" "),a("el-table-column",{attrs:{label:"访问时间"},scopedSlots:t._u([{key:"default",fn:function(e){return[t._v("\n "+t._s(t._f("dateformat")(e.row.time))+"\n ")]}}])})],1)],1)},i=[],r=(a("c1df"),a("bfad")),o=a("14c9"),c=a("c3cc"),s={name:"ShortLinkData",components:{LineChart:o["a"]},data:function(){return{title:"",list:[],chartData:{PvUv:{pv:[],uv:[],dates:[]}},startDate:null,endDate:null}},created:function(){this.title='"'.concat(this.$route.params.id,'" 近7日的数据');var t=Object(c["b"])(7);this.chartData.PvUv.dates=t.dates,this.getRequestHistoriesByDateRange(this.$route.params.id,t.startDate.format("YYYY-MM-DD"),t.endDate.format("YYYY-MM-DD"))},methods:{getRequestHistoriesByDateRange:function(t,e,a){var n=this;Object(r["e"])(t,e,a).then((function(t){n.list=t.data.histories;var e=Object(c["a"])(n.chartData.PvUv.dates,t.data.histories);n.chartData.PvUv.pv=e.pv,n.chartData.PvUv.uv=e.uv}))},back:function(){this.$router.go(-1)}}},l=s,u=a("2877"),h=Object(u["a"])(l,n,i,!1,null,"5f58dab4",null);e["default"]=h.exports}}]);
\ No newline at end of file
diff --git a/web/admin/static/js/chunk-60a4aa86.399c75e0.js b/web/admin/static/js/chunk-60a4aa86.399c75e0.js
deleted file mode 100644
index b7b640a..0000000
--- a/web/admin/static/js/chunk-60a4aa86.399c75e0.js
+++ /dev/null
@@ -1,8 +0,0 @@
-(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-60a4aa86"],{9472:function(e,t,r){"use strict";r.r(t);var n=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("el-main",[r("el-drawer",{ref:"createFormDrawer",attrs:{visible:e.createFormDrawer,direction:"rtl","before-close":e.handleCreateFormDrawerClose},on:{"update:visible":function(t){e.createFormDrawer=t}}},[r("div",{staticStyle:{width:"90%","margin-left":"15px"}},[r("h2",{staticStyle:{"margin-top":"0",color:"#606266"}},[e._v("添加短链接")]),e._v(" "),r("el-form",{ref:"createForm",attrs:{model:e.createForm,rules:e.createFormRules}},[r("el-form-item",{directives:[{name:"show",rawName:"v-show",value:2===e.role,expression:"role === 2"}],attrs:{label:"指定 ID",prop:"id"}},[r("el-switch",{on:{change:function(t){return e.specifyIdChange(t)}},model:{value:e.createForm.specifyId,callback:function(t){e.$set(e.createForm,"specifyId",t)},expression:"createForm.specifyId"}}),e._v(" "),r("el-popover",{attrs:{placement:"bottom",width:"320",trigger:"hover"}},[r("p",[e._v("设置你期望的ID,设置后随机ID将不起作用。")]),e._v(" "),r("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})]),e._v(" "),r("el-input",{directives:[{name:"show",rawName:"v-show",value:e.createForm.specifyId,expression:"createForm.specifyId"}],attrs:{disabled:e.createForm.setIdLength,placeholder:"示例:home"},model:{value:e.createForm.id,callback:function(t){e.$set(e.createForm,"id",t)},expression:"createForm.id"}})],1),e._v(" "),r("el-form-item",{directives:[{name:"show",rawName:"v-show",value:2===e.role,expression:"role === 2"}],attrs:{label:"指定随机 ID 长度",prop:"id_length"}},[r("el-switch",{on:{change:function(t){return e.setIdLengthChange(t)}},model:{value:e.createForm.setIdLength,callback:function(t){e.$set(e.createForm,"setIdLength",t)},expression:"createForm.setIdLength"}}),e._v(" "),r("el-popover",{attrs:{placement:"bottom",width:"320",trigger:"hover"}},[r("p",[e._v("在允许的范围内指定随机ID的长度,不指定时会使用系统默认设置。")]),e._v(" "),r("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})]),e._v(" "),r("el-slider",{directives:[{name:"show",rawName:"v-show",value:e.createForm.setIdLength,expression:"createForm.setIdLength"}],attrs:{"show-input":"",disabled:e.createForm.specifyId,min:e.idConfig.idMinimumLength,max:e.idConfig.idMaximumLength},model:{value:e.createForm.id_length,callback:function(t){e.$set(e.createForm,"id_length",t)},expression:"createForm.id_length"}})],1),e._v(" "),r("el-form-item",{attrs:{label:"目标链接",prop:"url"}},[r("el-input",{attrs:{placeholder:"示例:https://github.com/jwma/jump-jump"},model:{value:e.createForm.url,callback:function(t){e.$set(e.createForm,"url",t)},expression:"createForm.url"}})],1),e._v(" "),r("el-form-item",{attrs:{label:"描述",prop:"description"}},[r("el-input",{attrs:{type:"textarea",placeholder:"示例:某某帖子使用"},model:{value:e.createForm.description,callback:function(t){e.$set(e.createForm,"description",t)},expression:"createForm.description"}})],1),e._v(" "),r("el-form-item",{attrs:{label:"启用?",prop:"is_enable"}},[r("el-switch",{model:{value:e.createForm.is_enable,callback:function(t){e.$set(e.createForm,"is_enable",t)},expression:"createForm.is_enable"}}),e._v(" "),r("el-popover",{attrs:{placement:"bottom",width:"320",trigger:"hover"}},[r("p",[e._v("开启后短链接可以正常被访问,关闭后短链接被访问时会告知用户访问的页面不存在。"),r("br"),e._v(" "),r("strong",[e._v("注意:关闭后不会统计短链接访问的数据。")])]),e._v(" "),r("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})])],1),e._v(" "),r("el-form-item",[r("el-button",{attrs:{size:"mini",type:"primary"},on:{click:e.onCreateFormSubmit}},[e._v("添加")]),e._v(" "),r("el-button",{attrs:{size:"mini"},on:{click:e.onCreateFormCancel}},[e._v("取消")])],1)],1)],1)]),e._v(" "),r("el-drawer",{ref:"editFormDrawer",attrs:{visible:e.editFormDrawer,direction:"rtl","before-close":e.handleEditFormDrawerClose},on:{"update:visible":function(t){e.editFormDrawer=t}}},[r("div",{staticStyle:{width:"90%","margin-left":"15px"}},[r("h2",{staticStyle:{"margin-top":"0",color:"#606266"}},[e._v("更新:"+e._s(e.editForm.id))]),e._v(" "),r("el-form",{ref:"editForm",attrs:{model:e.editForm,rules:e.editFormRules}},[r("el-form-item",{attrs:{label:"目标链接",prop:"url"}},[r("el-input",{attrs:{placeholder:"示例:https://github.com/jwma/jump-jump"},model:{value:e.editForm.url,callback:function(t){e.$set(e.editForm,"url",t)},expression:"editForm.url"}})],1),e._v(" "),r("el-form-item",{attrs:{label:"描述",prop:"description"}},[r("el-input",{attrs:{type:"textarea",placeholder:"示例:某某帖子使用"},model:{value:e.editForm.description,callback:function(t){e.$set(e.editForm,"description",t)},expression:"editForm.description"}})],1),e._v(" "),r("el-form-item",{attrs:{label:"启用?",prop:"is_enable"}},[r("el-switch",{model:{value:e.editForm.is_enable,callback:function(t){e.$set(e.editForm,"is_enable",t)},expression:"editForm.is_enable"}}),e._v(" "),r("el-popover",{attrs:{placement:"bottom",width:"320",trigger:"hover"}},[r("p",[e._v("开启后短链接可以正常被访问,关闭后短链接被访问时会告知用户访问的页面不存在。"),r("br"),e._v(" "),r("strong",[e._v("注意:关闭后不会统计短链接访问的数据。")])]),e._v(" "),r("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})])],1),e._v(" "),r("el-form-item",{attrs:{label:"创建人"}},[r("span",{staticStyle:{color:"#909399"}},[e._v(e._s(e.editForm.created_by))])]),e._v(" "),r("el-form-item",{attrs:{label:"添加时间"}},[r("span",{staticStyle:{color:"#909399"}},[e._v(e._s(e._f("dateformat")(e.editForm.create_time)))])]),e._v(" "),r("el-form-item",{attrs:{label:"更新时间"}},[r("span",{staticStyle:{color:"#909399"}},[e._v(e._s(e._f("dateformat")(e.editForm.update_time)))])]),e._v(" "),r("el-form-item",[r("el-button",{attrs:{size:"mini",type:"primary"},on:{click:e.onEditFormSubmit}},[e._v("更新")]),e._v(" "),r("el-button",{attrs:{size:"mini"},on:{click:e.onEditFormCancel}},[e._v("取消")])],1)],1)],1)]),e._v(" "),r("el-button",{attrs:{icon:"el-icon-refresh",size:"mini"},on:{click:function(t){return e.getList(e.currentPage)}}},[e._v("刷新")]),e._v(" "),r("el-button",{attrs:{icon:"el-icon-plus",size:"mini",type:"primary"},on:{click:function(t){return e.toCreate()}}},[e._v("添加\n ")]),e._v(" "),r("el-table",{staticStyle:{width:"100%"},attrs:{data:e.list,"max-height":"800",fit:""}},[r("el-table-column",{attrs:{label:"短链接",width:"250"},scopedSlots:e._u([{key:"default",fn:function(t){return[r("i",{class:{"el-icon-star-off":-1==e.pinned.indexOf(t.row.id),"el-icon-star-on":-1!=e.pinned.indexOf(t.row.id)},staticStyle:{cursor:"pointer"},on:{click:function(r){return e.pin(t.row.id)}}}),e._v(" "),r("el-dropdown",{attrs:{size:"small"}},[r("span",{staticClass:"el-dropdown-link",staticStyle:{cursor:"pointer"}},[e._v("\n "+e._s(t.row.id)),r("i",{staticClass:"el-icon-arrow-down el-icon--right"})]),e._v(" "),r("el-dropdown-menu",{attrs:{slot:"dropdown"},slot:"dropdown"},e._l(e.landingHosts,(function(n){return r("el-dropdown-item",[r("span",{on:{click:function(r){return e.copyShortLink(n+t.row.id,r)}}},[e._v(e._s(n+t.row.id))])])})),1)],1)]}}])}),e._v(" "),r("el-table-column",{attrs:{prop:"url",label:"目标链接",width:"250"},scopedSlots:e._u([{key:"default",fn:function(t){return[r("el-dropdown",{attrs:{size:"small"}},[r("span",{staticClass:"el-dropdown-link",staticStyle:{cursor:"pointer"}},[r("span",{staticStyle:{width:"200px",overflow:"hidden","text-overflow":"ellipsis","white-space":"nowrap",display:"inline-block"}},[e._v(e._s(t.row.url))])]),e._v(" "),r("el-dropdown-menu",{attrs:{slot:"dropdown"},slot:"dropdown"},[r("el-dropdown-item",{staticStyle:{"line-height":"18px"}},[r("span",{on:{click:function(r){return e.copyShortLink(t.row.url,r)}}},[e._v(e._s(t.row.url))])])],1)],1)]}}])}),e._v(" "),r("el-table-column",{attrs:{label:"描述",width:"300"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.description?t.row.description:"-")+"\n ")]}}])}),e._v(" "),r("el-table-column",{attrs:{label:"启用?",width:"70",align:"center"},scopedSlots:e._u([{key:"default",fn:function(e){return[r("i",{class:{"el-icon-check":e.row.is_enable,"el-icon-close":!e.row.is_enable}})]}}])}),e._v(" "),r("el-table-column",{attrs:{label:"创建人",width:"150",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.created_by)+"\n ")]}}])}),e._v(" "),r("el-table-column",{attrs:{label:"添加时间",width:"100"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(e._f("dateformat")(t.row.create_time,"DD/MM/YY"))+"\n ")]}}])}),e._v(" "),r("el-table-column",{attrs:{label:"更新时间",width:"100"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(e._f("dateformat")(t.row.update_time,"DD/MM/YY"))+"\n ")]}}])}),e._v(" "),r("el-table-column",{attrs:{label:"操作"},scopedSlots:e._u([{key:"default",fn:function(t){return[r("el-button",{attrs:{size:"mini",circle:"",icon:"el-icon-s-data"},on:{click:function(r){return e.goto({name:"ShortLinkData",params:{id:t.row.id}})}}}),e._v(" "),r("el-button",{attrs:{size:"mini",circle:"",icon:"el-icon-edit-outline"},on:{click:function(r){return e.toEdit(t.row.id)}}}),e._v(" "),r("el-button",{attrs:{type:"danger",size:"mini",icon:"el-icon-delete-solid",circle:""},on:{click:function(r){return e.deleteShortLink(t.row.id)}}})]}}])})],1),e._v(" "),r("div",{staticClass:"paginator-container"},[r("el-pagination",{attrs:{"current-page":e.currentPage,"page-sizes":[10,20,30],"page-size":e.pageSize,layout:"total, sizes, prev, pager, next, jumper",total:e.total},on:{"size-change":e.handlePageSizeChange,"current-change":e.handleCurrentPageChange}})],1)],1)},i=[],o=r("db72"),a=r("bfad"),c=r("da71"),s=r("61f7"),l=r("2b0e"),u=r("b311"),d=r.n(u);function f(){l["default"].prototype.$message({message:"复制成功",type:"success",duration:1500})}function h(){l["default"].prototype.$message({message:"复制失败",type:"error"})}function m(e,t){var r=new d.a(t.target,{text:function(){return e}});r.on("success",(function(){f(),r.off("error"),r.off("success"),r.destroy()})),r.on("error",(function(){h(),r.off("error"),r.off("success"),r.destroy()})),r.onClick(t)}var p=r("2f62"),g={name:"ShortLinkList",data:function(){var e=function(e,t,r){""!==t?r():r(new Error("请输入目标链接"))};return{landingHosts:[],list:[],total:0,currentPage:1,pageSize:20,createFormDrawer:!1,idConfig:{idMinimumLength:0,idLength:0,idMaximumLength:0},createForm:{specifyId:!1,setIdLength:!1,id:"",url:"",description:"",is_enable:!1,id_length:0},createFormRules:{url:[{required:!0,validator:e,trigger:"blur"}]},editFormDrawer:!1,editForm:{id:"",url:"",description:"",is_enable:!1,created_by:"",create_time:"",update_time:""},editFormRules:{url:[{validator:e,trigger:"blur"}]}}},beforeRouteUpdate:function(e,t,r){this.currentPage=e.query.page||this.currentPage,this.pageSize=e.query.pageSize||this.pageSize,this.getList(this.currentPage),r()},created:function(){var e=this;this.currentPage=parseInt(this.$route.query.page)||this.currentPage,this.pageSize=parseInt(this.$route.query.pageSize)||this.pageSize,Object(c["a"])().then((function(t){e.landingHosts=t.data.config.landingHosts,e.idConfig=t.data.config.idConfig,e.createForm.id_length=e.idConfig.idLength,e.getList(e.currentPage)}))},computed:Object(o["a"])({},Object(p["b"])(["role","pinned"])),methods:{goto:function(e){this.$router.push(e)},copyShortLink:function(e,t){m(e,t)},getList:function(e){var t=this;Object(a["c"])(e,this.pageSize).then((function(r){t.currentPage=e,t.total=r.data.total,t.list=r.data.shortLinks,1!==t.currentPage&&0===t.list.length&&t.total>0&&(t.currentPage=1,t.getList(1))}))},resetCreateForm:function(){this.createForm.specifyId=!1,this.createForm.setIdLength=!1,this.createForm.id="",this.createForm.url="",this.createForm.description="",this.createForm.is_enable=!1},resetEditForm:function(){this.editForm.url="",this.editForm.description="",this.editForm.is_enable=!1,this.editForm.created_by="",this.editForm.create_time="",this.editForm.update_time=""},getInvalidUrlTipsText:function(e){return'
目标链接不是常规的URL,确定继续?")},handlePageSizeChange:function(e){this.pageSize=e,this.currentPage=1,this.$router.push({name:"ShortLinkList",query:{page:1,pageSize:e}})},handleCurrentPageChange:function(e){this.currentPage=e,this.$router.push({name:"ShortLinkList",query:{page:e,pageSize:this.pageSize}})},toCreate:function(){var e=this;Object(c["a"])().then((function(t){e.idConfig=t.data.config.idConfig,e.createForm.id_length=e.idConfig.idLength,e.createFormDrawer=!0}))},handleCreateFormDrawerClose:function(e){this.resetCreateForm(),e()},submitCreateForm:function(){var e=this;Object(a["a"])(this.createForm).then((function(t){e.$refs.createFormDrawer.closeDrawer(),e.$notify({title:"添加短链接成功",message:"ID:"+t.data.shortLink.id,type:"success"}),e.getList(e.currentPage)}))},onCreateFormSubmit:function(){var e=this;this.$refs.createForm.validate((function(t){if(!t)return!1;Object(s["b"])(e.createForm.url)?e.submitCreateForm():e.$confirm(e.getInvalidUrlTipsText(e.createForm.url),"提示",{confirmButtonText:"确定",cancelButtonText:"再改改",type:"warning",dangerouslyUseHTMLString:!0}).then((function(){e.submitCreateForm()}))}))},onCreateFormCancel:function(){this.resetCreateForm(),this.createFormDrawer=!1},toEdit:function(e){var t=this;Object(a["d"])(e).then((function(e){t.editFormDrawer=!0,t.editForm=e.data.shortLink}))},handleEditFormDrawerClose:function(e){this.resetEditForm(),e()},submitEditForm:function(){var e=this;Object(a["g"])(this.editForm.id,this.editForm).then((function(t){e.$refs.editFormDrawer.closeDrawer(),e.$notify({title:"更新成功",message:"ID:"+t.data.shortLink.id,type:"success"}),e.getList(e.currentPage)}))},onEditFormSubmit:function(){var e=this;this.$refs.editForm.validate((function(t){if(!t)return!1;Object(s["b"])(e.editForm.url)?e.submitEditForm():e.$confirm(e.getInvalidUrlTipsText(e.editForm.url),"提示",{confirmButtonText:"确定",cancelButtonText:"再改改",type:"warning",dangerouslyUseHTMLString:!0}).then((function(){e.submitEditForm()}))}))},onEditFormCancel:function(){this.resetEditForm(),this.editFormDrawer=!1},deleteShortLink:function(e){var t=this;this.$confirm("此操作会永久删除短链接,是否继续?","删除确认",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then((function(){Object(a["f"])(e).then((function(r){t.$notify({title:"成功删除短链接",message:"ID:".concat(e),type:"success"}),t.getList(t.currentPage),t.$store.dispatch("link/unpin",e)}))}))},specifyIdChange:function(e){e?(this.createForm.setIdLength=!1,this.setIdLengthChange(!1)):this.createForm.id=""},setIdLengthChange:function(e){e?(this.createForm.specifyId=!1,this.specifyIdChange(!1)):this.createForm.id_length=this.idConfig.idLength},pin:function(e){-1==this.pinned.indexOf(e)?(this.$store.dispatch("link/pin",e),this.$message({showClose:!0,type:"success",message:"Pin ".concat(e)})):(this.$store.dispatch("link/unpin",e),this.$message({showClose:!0,type:"success",message:"Unpin ".concat(e)}))}}},v=g,b=(r("c559"),r("2877")),y=Object(b["a"])(v,n,i,!1,null,"23d33577",null);t["default"]=y.exports},b311:function(e,t,r){
-/*!
- * clipboard.js v2.0.6
- * https://clipboardjs.com/
- *
- * Licensed MIT © Zeno Rocha
- */
-(function(t,r){e.exports=r()})(0,(function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=6)}([function(e,t){function r(e){var t;if("SELECT"===e.nodeName)e.focus(),t=e.value;else if("INPUT"===e.nodeName||"TEXTAREA"===e.nodeName){var r=e.hasAttribute("readonly");r||e.setAttribute("readonly",""),e.select(),e.setSelectionRange(0,e.value.length),r||e.removeAttribute("readonly"),t=e.value}else{e.hasAttribute("contenteditable")&&e.focus();var n=window.getSelection(),i=document.createRange();i.selectNodeContents(e),n.removeAllRanges(),n.addRange(i),t=n.toString()}return t}e.exports=r},function(e,t){function r(){}r.prototype={on:function(e,t,r){var n=this.e||(this.e={});return(n[e]||(n[e]=[])).push({fn:t,ctx:r}),this},once:function(e,t,r){var n=this;function i(){n.off(e,i),t.apply(r,arguments)}return i._=t,this.on(e,i,r)},emit:function(e){var t=[].slice.call(arguments,1),r=((this.e||(this.e={}))[e]||[]).slice(),n=0,i=r.length;for(n;n0&&void 0!==arguments[0]?arguments[0]:{};this.action=e.action,this.container=e.container,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""}},{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var e=this,t="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return e.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[t?"right":"left"]="-9999px";var r=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=r+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=i()(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=i()(this.target),this.copyText()}},{key:"copyText",value:function(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function(e){this.emitter.emit(e?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),document.activeElement.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(e){if(void 0!==e){if(!e||"object"!==("undefined"===typeof e?"undefined":o(e))||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=e}},get:function(){return this._target}}]),e}(),l=s,u=r(1),d=r.n(u),f=r(2),h=r.n(f),m="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"===typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},p=function(){function e(e,t){for(var r=0;r0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"===typeof e.action?e.action:this.defaultAction,this.target="function"===typeof e.target?e.target:this.defaultTarget,this.text="function"===typeof e.text?e.text:this.defaultText,this.container="object"===m(e.container)?e.container:document.body}},{key:"listenClick",value:function(e){var t=this;this.listener=h()(e,"click",(function(e){return t.onClick(e)}))}},{key:"onClick",value:function(e){var t=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new l({action:this.action(t),target:this.target(t),text:this.text(t),container:this.container,trigger:t,emitter:this})}},{key:"defaultAction",value:function(e){return _("action",e)}},{key:"defaultTarget",value:function(e){var t=_("target",e);if(t)return document.querySelector(t)}},{key:"defaultText",value:function(e){return _("text",e)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],t="string"===typeof e?[e]:e,r=!!document.queryCommandSupported;return t.forEach((function(e){r=r&&!!document.queryCommandSupported(e)})),r}}]),t}(d.a);function _(e,t){var r="data-clipboard-"+e;if(t.hasAttribute(r))return t.getAttribute(r)}t["default"]=y}])["default"]}))},bfad:function(e,t,r){"use strict";r.d(t,"d",(function(){return i})),r.d(t,"c",(function(){return o})),r.d(t,"a",(function(){return a})),r.d(t,"f",(function(){return c})),r.d(t,"g",(function(){return s})),r.d(t,"b",(function(){return l})),r.d(t,"e",(function(){return u}));var n=r("b775");function i(e){return Object(n["a"])({url:"/v1/short-link/".concat(e),method:"get"})}function o(e,t){return Object(n["a"])({url:"/v1/short-link/?page=".concat(e,"&pageSize=").concat(t),method:"get"})}function a(e){return Object(n["a"])({url:"/v1/short-link/",method:"post",data:e})}function c(e){return Object(n["a"])({url:"/v1/short-link/".concat(e),method:"delete"})}function s(e,t){return Object(n["a"])({url:"/v1/short-link/".concat(e),method:"patch",data:t})}function l(e,t){return Object(n["a"])({url:"/v1/short-link/".concat(e,"/latest-request-history?size=").concat(t),method:"get"})}function u(e,t,r){return Object(n["a"])({url:"/v1/short-link/".concat(e,"/data?startDate=").concat(t,"&endDate=").concat(r),method:"get"})}},c559:function(e,t,r){"use strict";var n=r("ce06"),i=r.n(n);i.a},ce06:function(e,t,r){},da71:function(e,t,r){"use strict";r.d(t,"a",(function(){return i})),r.d(t,"c",(function(){return o})),r.d(t,"b",(function(){return a})),r.d(t,"d",(function(){return c}));var n=r("b775");function i(){return Object(n["a"])({url:"/v1/config",method:"get"})}function o(e){return Object(n["a"])({url:"/v1/config/landing-hosts",method:"patch",data:e})}function a(e){return Object(n["a"])({url:"/v1/config/id-length",method:"patch",data:e})}function c(e){return Object(n["a"])({url:"/v1/config/short-link-404-handling",method:"patch",data:e})}}}]);
\ No newline at end of file
diff --git a/web/admin/static/js/chunk-672304de.4615defb.js b/web/admin/static/js/chunk-672304de.4615defb.js
deleted file mode 100644
index bb02ac1..0000000
--- a/web/admin/static/js/chunk-672304de.4615defb.js
+++ /dev/null
@@ -1 +0,0 @@
-(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-672304de"],{"02f4":function(t,e,r){var n=r("4588"),a=r("be13");t.exports=function(t){return function(e,r){var c,o,i=String(a(e)),u=n(r),l=i.length;return u<0||u>=l?t?"":void 0:(c=i.charCodeAt(u),c<55296||c>56319||u+1===l||(o=i.charCodeAt(u+1))<56320||o>57343?t?i.charAt(u):c:t?i.slice(u,u+2):o-56320+(c-55296<<10)+65536)}}},"0390":function(t,e,r){"use strict";var n=r("02f4")(!0);t.exports=function(t,e,r){return e+(r?n(t,e).length:1)}},"07e5":function(t,e,r){"use strict";r.r(e);var n=function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("el-main",[r("el-page-header",{attrs:{content:t.title},on:{back:t.back}}),t._v(" "),r("el-divider"),t._v(" "),r("el-table",{attrs:{data:t.list,size:"mini"}},[r("el-table-column",{attrs:{prop:"url",label:"目标链接",width:"300"},scopedSlots:t._u([{key:"default",fn:function(e){return[r("el-link",{attrs:{type:"info",href:e.row.url,target:"_blank"}},[t._v(t._s(e.row.url))])]}}])}),t._v(" "),r("el-table-column",{attrs:{prop:"ip",label:"IP",width:"200"}}),t._v(" "),r("el-table-column",{attrs:{prop:"ua",label:"User Agent"}}),t._v(" "),r("el-table-column",{attrs:{label:"访问时间"},scopedSlots:t._u([{key:"default",fn:function(e){return[t._v("\n "+t._s(t._f("dateformat")(e.row.time))+"\n ")]}}])})],1)],1)},a=[],c=(r("a481"),r("bfad")),o={name:"LatestRequestHistory",data:function(){return{title:"",list:[]}},created:function(){var t=this.$route.params.id;this.title="".concat(t," 的最近访问记录"),this.getLatestRequestHistory(t)},methods:{getLatestRequestHistory:function(t){var e=this;Object(c["b"])(t,this.$route.query.size||20).then((function(t){e.list=t.data.histories}))},back:function(){this.$router.replace("/short-link")}}},i=o,u=r("2877"),l=Object(u["a"])(i,n,a,!1,null,"7fefcfa9",null);e["default"]=l.exports},"214f":function(t,e,r){"use strict";r("b0c5");var n=r("2aba"),a=r("32e9"),c=r("79e5"),o=r("be13"),i=r("2b4c"),u=r("520a"),l=i("species"),s=!c((function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")})),f=function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var r="ab".split(t);return 2===r.length&&"a"===r[0]&&"b"===r[1]}();t.exports=function(t,e,r){var d=i(t),v=!c((function(){var e={};return e[d]=function(){return 7},7!=""[t](e)})),h=v?!c((function(){var e=!1,r=/a/;return r.exec=function(){return e=!0,null},"split"===t&&(r.constructor={},r.constructor[l]=function(){return r}),r[d](""),!e})):void 0;if(!v||!h||"replace"===t&&!s||"split"===t&&!f){var p=/./[d],b=r(o,d,""[t],(function(t,e,r,n,a){return e.exec===u?v&&!a?{done:!0,value:p.call(e,r,n)}:{done:!0,value:t.call(r,e,n)}:{done:!1}})),g=b[0],x=b[1];n(String.prototype,t,g),a(RegExp.prototype,d,2==e?function(t,e){return x.call(t,this,e)}:function(t){return x.call(t,this)})}}},"520a":function(t,e,r){"use strict";var n=r("0bfb"),a=RegExp.prototype.exec,c=String.prototype.replace,o=a,i="lastIndex",u=function(){var t=/a/,e=/b*/g;return a.call(t,"a"),a.call(e,"a"),0!==t[i]||0!==e[i]}(),l=void 0!==/()??/.exec("")[1],s=u||l;s&&(o=function(t){var e,r,o,s,f=this;return l&&(r=new RegExp("^"+f.source+"$(?!\\s)",n.call(f))),u&&(e=f[i]),o=a.call(f,t),u&&o&&(f[i]=f.global?o.index+o[0].length:e),l&&o&&o.length>1&&c.call(o[0],r,(function(){for(s=1;s]*>)/g,v=/\$([$&`']|\d\d?)/g,h=function(t){return void 0===t?t:String(t)};r("214f")("replace",2,(function(t,e,r,p){return[function(n,a){var c=t(this),o=void 0==n?void 0:n[e];return void 0!==o?o.call(n,c,a):r.call(String(c),n,a)},function(t,e){var a=p(r,t,this,e);if(a.done)return a.value;var f=n(t),d=String(this),v="function"===typeof e;v||(e=String(e));var g=f.global;if(g){var x=f.unicode;f.lastIndex=0}var m=[];while(1){var k=u(f,d);if(null===k)break;if(m.push(k),!g)break;var y=String(k[0]);""===y&&(f.lastIndex=i(d,c(f.lastIndex),x))}for(var w="",_=0,S=0;S=_&&(w+=d.slice(_,j)+q,_=j+$.length)}return w+d.slice(_)}];function b(t,e,n,c,o,i){var u=n+t.length,l=c.length,s=v;return void 0!==o&&(o=a(o),s=d),r.call(i,s,(function(r,a){var i;switch(a.charAt(0)){case"$":return"$";case"&":return t;case"`":return e.slice(0,n);case"'":return e.slice(u);case"<":i=o[a.slice(1,-1)];break;default:var s=+a;if(0===s)return r;if(s>l){var d=f(s/10);return 0===d?r:d<=l?void 0===c[d-1]?a.charAt(1):c[d-1]+a.charAt(1):r}i=c[s-1]}return void 0===i?"":i}))}}))},b0c5:function(t,e,r){"use strict";var n=r("520a");r("5ca1")({target:"RegExp",proto:!0,forced:n!==/./.exec},{exec:n})},bfad:function(t,e,r){"use strict";r.d(e,"d",(function(){return a})),r.d(e,"c",(function(){return c})),r.d(e,"a",(function(){return o})),r.d(e,"f",(function(){return i})),r.d(e,"g",(function(){return u})),r.d(e,"b",(function(){return l})),r.d(e,"e",(function(){return s}));var n=r("b775");function a(t){return Object(n["a"])({url:"/v1/short-link/".concat(t),method:"get"})}function c(t,e){return Object(n["a"])({url:"/v1/short-link/?page=".concat(t,"&pageSize=").concat(e),method:"get"})}function o(t){return Object(n["a"])({url:"/v1/short-link/",method:"post",data:t})}function i(t){return Object(n["a"])({url:"/v1/short-link/".concat(t),method:"delete"})}function u(t,e){return Object(n["a"])({url:"/v1/short-link/".concat(t),method:"patch",data:e})}function l(t,e){return Object(n["a"])({url:"/v1/short-link/".concat(t,"/latest-request-history?size=").concat(e),method:"get"})}function s(t,e,r){return Object(n["a"])({url:"/v1/short-link/".concat(t,"/data?startDate=").concat(e,"&endDate=").concat(r),method:"get"})}}}]);
\ No newline at end of file
diff --git a/web/admin/static/js/chunk-7f8ff64d.e42f1527.js b/web/admin/static/js/chunk-7f8ff64d.0553663a.js
similarity index 84%
rename from web/admin/static/js/chunk-7f8ff64d.e42f1527.js
rename to web/admin/static/js/chunk-7f8ff64d.0553663a.js
index f22d0ba..dbec205 100644
--- a/web/admin/static/js/chunk-7f8ff64d.e42f1527.js
+++ b/web/admin/static/js/chunk-7f8ff64d.0553663a.js
@@ -1 +1 @@
-(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-7f8ff64d"],{"14c9":function(t,n,e){"use strict";var o=function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("div",{class:t.className,style:{height:t.height,width:t.width}})},i=[],r=e("313e"),a=e.n(r);e("817d");var s={props:{className:{type:String,default:"chart"},width:{type:String,default:"100%"},height:{type:String,default:"350px"},autoResize:{type:Boolean,default:!0},chartData:{type:Object,required:!0},title:{type:Object,default:{}}},data:function(){return{chart:null}},watch:{chartData:{deep:!0,handler:function(t){this.setOptions(t)}}},mounted:function(){var t=this;this.$nextTick((function(){t.initChart()}))},beforeDestroy:function(){this.chart&&(this.chart.dispose(),this.chart=null)},methods:{initChart:function(){this.chart=a.a.init(this.$el,"macarons"),this.setOptions(this.chartData)},setOptions:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.pv,e=t.uv,o=t.dates;this.chart&&this.chart.setOption({title:this.title,xAxis:{data:o,boundaryGap:!1,axisTick:{show:!1}},grid:{left:50,right:50,bottom:20,top:30,containLabel:!0},tooltip:{trigger:"axis",axisPointer:{type:"cross"},padding:[5,10]},yAxis:{axisTick:{show:!1}},legend:{data:["PV","UV"]},series:[{name:"PV",itemStyle:{normal:{color:"#FF005A",lineStyle:{color:"#FF005A",width:2}}},smooth:!0,type:"line",data:n,animationDuration:2800,animationEasing:"cubicInOut"},{name:"UV",smooth:!0,type:"line",itemStyle:{normal:{color:"#3888fa",lineStyle:{color:"#3888fa",width:2},areaStyle:{color:"#f3f8ff"}}},data:e,animationDuration:2800,animationEasing:"quadraticOut"}]})}}},l=s,c=e("2877"),u=Object(c["a"])(l,o,i,!1,null,null,null);n["a"]=u.exports},"1af6":function(t,n,e){var o=e("63b6");o(o.S,"Array",{isArray:e("9003")})},"549b":function(t,n,e){"use strict";var o=e("d864"),i=e("63b6"),r=e("241e"),a=e("b0dc"),s=e("3702"),l=e("b447"),c=e("20fd"),u=e("7cd6");i(i.S+i.F*!e("4ee1")((function(t){Array.from(t)})),"Array",{from:function(t){var n,e,i,d,f=r(t),h="function"==typeof this?this:Array,m=arguments.length,v=m>1?arguments[1]:void 0,g=void 0!==v,p=0,b=u(f);if(g&&(v=o(v,m>2?arguments[2]:void 0,2)),void 0==b||h==Array&&s(b))for(n=l(f.length),e=new h(n);n>p;p++)c(e,p,g?v(f[p],p):f[p]);else for(d=b.call(f),e=new h;!(i=d.next()).done;p++)c(e,p,g?a(d,v,[i.value,p],!0):i.value);return e.length=p,e}})},"54a1":function(t,n,e){e("6c1c"),e("1654"),t.exports=e("95d5")},"774e":function(t,n,e){t.exports=e("d2d5")},9406:function(t,n,e){"use strict";e.r(n);var o=function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("el-main",[e("el-row",{directives:[{name:"show",rawName:"v-show",value:t.pinned.length>0,expression:"pinned.length > 0"}],attrs:{gutter:5}},[e("h3",{staticStyle:{color:"#555"}},[t._v("Pin")]),t._v(" "),t._l(t.pinned,(function(n,o){return e("el-col",{attrs:{span:8}},[e("line-chart",{attrs:{title:{text:n,align:"right"},"chart-data":{pv:t.pinnedLinksData.perDayPvUv[n].pv,uv:t.pinnedLinksData.perDayPvUv[n].uv,dates:t.pinnedLinksData.dates},height:"200px"}})],1)}))],2),t._v(" "),t.pinned.length>0?e("el-divider"):t._e(),t._v(" "),e("el-row",{attrs:{gutter:20}},[e("h3",{staticStyle:{color:"#555"}},[t._v("系统设置")]),t._v(" "),e("el-col",{attrs:{span:7}},[e("el-card",[e("div",{staticClass:"clearfix",attrs:{slot:"header"},slot:"header"},[e("span",[t._v("短链接域名\n "),e("el-popover",{attrs:{placement:"bottom",width:"300",trigger:"hover"}},[e("p",[t._v("\n 配置短链接域名后,可以在短链接列表快速拷贝完整的短链接。"),e("br"),t._v("\n 示例:http://t.anmuji.com/"),e("br"),t._v(" "),e("strong",[t._v('注意:以 "/" 结尾。')])]),t._v(" "),e("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})])],1),t._v(" "),e("div",{directives:[{name:"show",rawName:"v-show",value:2===t.role,expression:"role === 2"}],staticStyle:{float:"right"}},[e("el-button",{attrs:{icon:"el-icon-refresh",size:"mini",circle:""},on:{click:function(n){return t.getConfig("landingHostsForm")}}}),t._v(" "),e("el-button",{attrs:{icon:"el-icon-plus",size:"mini",circle:""},on:{click:function(n){return t.addLandingHost()}}}),t._v(" "),e("el-button",{attrs:{icon:"el-icon-check",size:"mini",circle:""},on:{click:function(n){return t.updateLadingHosts()}}})],1)]),t._v(" "),e("el-form",{ref:"landingHostsForm",attrs:{model:t.landingHostsForm,"label-position":"left","label-width":"0px",size:"mini"}},t._l(t.landingHostsForm.hosts,(function(n,o){return e("el-form-item",{key:n.key,attrs:{prop:"hosts."+o+".value",rules:t.landingHostRules}},[e("el-input",{staticStyle:{width:"90%"},attrs:{readonly:2!==t.role,placeholder:"示例:http://anmuji.com/t/ 以 / 结尾"},model:{value:n.value,callback:function(e){t.$set(n,"value",e)},expression:"host.value"}}),t._v(" "),e("el-button",{directives:[{name:"show",rawName:"v-show",value:t.landingHostsForm.hosts.length>1&&2===t.role,expression:"landingHostsForm.hosts.length > 1 && role === 2"}],staticStyle:{padding:"1px"},attrs:{icon:"el-icon-minus",size:"mini",type:"danger",circle:""},on:{click:function(n){return t.removeLandingHost(o)}}})],1)})),1)],1)],1),t._v(" "),e("el-col",{attrs:{span:10}},[e("el-card",[e("div",{staticClass:"clearfix",attrs:{slot:"header"},slot:"header"},[e("span",[t._v("随机 ID 长度设置\n "),e("el-popover",{attrs:{placement:"bottom",width:"300",trigger:"hover"}},[e("p",[t._v("默认长度即随机生成 ID 的长度,"),e("br"),t._v("最小长度 <= 默认长度 <= 最大长度")]),t._v(" "),e("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})])],1),t._v(" "),e("div",{directives:[{name:"show",rawName:"v-show",value:2===t.role,expression:"role === 2"}],staticStyle:{float:"right"}},[e("el-button",{attrs:{icon:"el-icon-refresh",size:"mini",circle:""},on:{click:function(n){return t.getConfig("idConfigForm")}}}),t._v(" "),e("el-button",{attrs:{icon:"el-icon-check",size:"mini",circle:""},on:{click:function(n){return t.updateIdLengthConfig()}}})],1)]),t._v(" "),e("el-form",{ref:"idConfigForm",attrs:{model:t.idConfigForm,size:"mini","label-position":"top",inline:!0}},[e("el-form-item",{attrs:{prop:"idMinimumLength",label:"最小长度"}},[e("el-input-number",{attrs:{size:"mini",disabled:2!==t.role},model:{value:t.idConfigForm.idMinimumLength,callback:function(n){t.$set(t.idConfigForm,"idMinimumLength",n)},expression:"idConfigForm.idMinimumLength"}})],1),t._v(" "),e("el-form-item",{attrs:{prop:"idLength",label:"默认长度"}},[e("el-input-number",{attrs:{size:"mini",disabled:2!==t.role},model:{value:t.idConfigForm.idLength,callback:function(n){t.$set(t.idConfigForm,"idLength",n)},expression:"idConfigForm.idLength"}})],1),t._v(" "),e("el-form-item",{attrs:{prop:"idMaximumLength",label:"最大长度"}},[e("el-input-number",{attrs:{size:"mini",disabled:2!==t.role},model:{value:t.idConfigForm.idMaximumLength,callback:function(n){t.$set(t.idConfigForm,"idMaximumLength",n)},expression:"idConfigForm.idMaximumLength"}})],1)],1)],1)],1),t._v(" "),e("el-col",{attrs:{span:7}},[e("el-card",[e("div",{staticClass:"clearfix",attrs:{slot:"header"},slot:"header"},[e("span",[t._v("短链接 404 处理\n "),e("el-popover",{attrs:{placement:"bottom",width:"320",trigger:"hover"}},[e("p",[t._v("展示文案:当访问的短链接找不到时,展示设定的文案")]),t._v(" "),e("p",[t._v("URL跳转:当访问的短链接找不到时,跳转到设定的URL")]),t._v(" "),e("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})])],1),t._v(" "),e("div",{directives:[{name:"show",rawName:"v-show",value:2===t.role,expression:"role === 2"}],staticStyle:{float:"right"}},[e("el-button",{attrs:{icon:"el-icon-refresh",size:"mini",circle:""},on:{click:function(n){return t.getConfig("shortLinkNotFoundConfigForm")}}}),t._v(" "),e("el-button",{attrs:{icon:"el-icon-check",size:"mini",circle:""},on:{click:function(n){return t.updateShortLinkNotFoundConfig()}}})],1)]),t._v(" "),e("el-form",{ref:"shortLinkNotFoundConfigForm",attrs:{model:t.shortLinkNotFoundConfigForm,size:"mini","label-position":"top"}},[e("el-form-item",{attrs:{prop:"mode",label:"模式"}},[e("el-select",{attrs:{placeholder:"请选择",disabled:2!==t.role},model:{value:t.shortLinkNotFoundConfigForm.mode,callback:function(n){t.$set(t.shortLinkNotFoundConfigForm,"mode",n)},expression:"shortLinkNotFoundConfigForm.mode"}},t._l(t.shortLinkNotFoundModeOptions,(function(t){return e("el-option",{key:t.value,attrs:{label:t.label,value:t.value}})})),1)],1),t._v(" "),e("el-form-item",{directives:[{name:"show",rawName:"v-show",value:"content"===t.shortLinkNotFoundConfigForm.mode,expression:"shortLinkNotFoundConfigForm.mode === 'content'"}],attrs:{prop:"value",label:"文案",rules:t.shortLinkNotFoundConfigRules}},[e("el-input",{attrs:{type:"textarea",placeholder:"你访问的页面不存在哦",readonly:2!==t.role},model:{value:t.shortLinkNotFoundConfigForm.value,callback:function(n){t.$set(t.shortLinkNotFoundConfigForm,"value",n)},expression:"shortLinkNotFoundConfigForm.value"}})],1),t._v(" "),e("el-form-item",{directives:[{name:"show",rawName:"v-show",value:"redirect"===t.shortLinkNotFoundConfigForm.mode,expression:"shortLinkNotFoundConfigForm.mode === 'redirect'"}],attrs:{prop:"value",label:"URL",rules:t.shortLinkNotFoundConfigRules}},[e("el-input",{attrs:{placeholder:"示例:https://github.com/jwma/jump-jump"},model:{value:t.shortLinkNotFoundConfigForm.value,callback:function(n){t.$set(t.shortLinkNotFoundConfigForm,"value",n)},expression:"shortLinkNotFoundConfigForm.value"}})],1)],1)],1)],1)],1)],1)},i=[],r=e("a745"),a=e.n(r);function s(t){if(a()(t)){for(var n=0,e=new Array(t.length);n0){var n=Object(L["b"])(7);this.pinnedLinksData.dates=n.dates,this.pinned.forEach((function(e,o){t.$set(t.pinnedLinksData.perDayPvUv,e,{pv:[],uv:[]}),t.getRequestHistoriesByDateRange(e,n.startDate.format("YYYY-MM-DD"),n.endDate.format("YYYY-MM-DD"))}))}},methods:{getConfig:function(t){var n=this;Object(g["a"])().then((function(e){"landingHostsForm"!==t&&"all"!==t||(n.landingHostsForm.hosts=[],e.data.config.landingHosts.forEach((function(t,e){n.landingHostsForm.hosts.push({value:t,key:Date.now()+e})})),0===e.data.config.landingHosts.length&&n.addLandingHost()),"idConfigForm"!==t&&"all"!==t||(n.idConfigForm.idMinimumLength=e.data.config.idConfig.idMinimumLength,n.idConfigForm.idLength=e.data.config.idConfig.idLength,n.idConfigForm.idMaximumLength=e.data.config.idConfig.idMaximumLength),"shortLinkNotFoundConfigForm"!==t&&"all"!==t||(n.shortLinkNotFoundConfigForm.mode=e.data.config.shortLinkNotFoundConfig.mode,n.shortLinkNotFoundConfigForm.value=e.data.config.shortLinkNotFoundConfig.value)}))},addLandingHost:function(){this.landingHostsForm.hosts.push({value:"",key:Date.now()})},removeLandingHost:function(t){this.landingHostsForm.hosts.splice(t,1)},updateLadingHosts:function(){var t=this;this.$refs["landingHostsForm"].validate((function(n){if(!n)return!1;var e=[];t.landingHostsForm.hosts.forEach((function(t){e.push(t.value)})),Object(g["c"])({hosts:e}).then((function(n){t.$notify({title:"更新成功",message:"成功更新短链接域名",type:"success"})}))}))},updateIdLengthConfig:function(){var t=this;Object(g["b"])(this.idConfigForm).then((function(n){t.$notify({title:"更新成功",message:"成功更新随机 ID 长度",type:"success"})}))},updateShortLinkNotFoundConfig:function(){var t=this;this.$refs["shortLinkNotFoundConfigForm"].validate((function(n){if(!n)return!1;Object(g["d"])(t.shortLinkNotFoundConfigForm).then((function(n){t.$notify({title:"更新成功",message:"短链接 404 处理配置",type:"success"})}))}))},getRequestHistoriesByDateRange:function(t,n,e){var o=this;Object(k["e"])(t,n,e).then((function(n){var e,i;o.list=n.data.histories;var r=Object(L["a"])(o.pinnedLinksData.dates,n.data.histories);(e=o.pinnedLinksData.perDayPvUv[t].pv).push.apply(e,m(r.pv)),(i=o.pinnedLinksData.perDayPvUv[t].uv).push.apply(i,m(r.uv))}))}}},y=C,w=(e("f8a7"),e("2877")),x=Object(w["a"])(y,o,i,!1,null,null,null);n["default"]=x.exports},"95d5":function(t,n,e){var o=e("40c3"),i=e("5168")("iterator"),r=e("481b");t.exports=e("584a").isIterable=function(t){var n=Object(t);return void 0!==n[i]||"@@iterator"in n||r.hasOwnProperty(o(n))}},a745:function(t,n,e){t.exports=e("f410")},acf4:function(t,n,e){},bfad:function(t,n,e){"use strict";e.d(n,"d",(function(){return i})),e.d(n,"c",(function(){return r})),e.d(n,"a",(function(){return a})),e.d(n,"f",(function(){return s})),e.d(n,"g",(function(){return l})),e.d(n,"b",(function(){return c})),e.d(n,"e",(function(){return u}));var o=e("b775");function i(t){return Object(o["a"])({url:"/v1/short-link/".concat(t),method:"get"})}function r(t,n){return Object(o["a"])({url:"/v1/short-link/?page=".concat(t,"&pageSize=").concat(n),method:"get"})}function a(t){return Object(o["a"])({url:"/v1/short-link/",method:"post",data:t})}function s(t){return Object(o["a"])({url:"/v1/short-link/".concat(t),method:"delete"})}function l(t,n){return Object(o["a"])({url:"/v1/short-link/".concat(t),method:"patch",data:n})}function c(t,n){return Object(o["a"])({url:"/v1/short-link/".concat(t,"/latest-request-history?size=").concat(n),method:"get"})}function u(t,n,e){return Object(o["a"])({url:"/v1/short-link/".concat(t,"/data?startDate=").concat(n,"&endDate=").concat(e),method:"get"})}},c3cc:function(t,n,e){"use strict";e.d(n,"b",(function(){return r})),e.d(n,"a",(function(){return a}));e("ac6a");var o=e("c1df"),i=e.n(o);function r(t){var n=i()(),e=n.clone().add(-(t-1),"d"),o=n.clone(),r=e.clone(),a=[];while(r.isSameOrBefore(o))a.push(r.format("YYYY-MM-DD")),r.add(1,"d");return{startDate:e,endDate:o,dates:a}}function a(t,n){var e={};t.forEach((function(t){e[t]={pv:0,ips:[]}})),n.forEach((function(t,n){var o=i()(t.time).format("YYYY-MM-DD");e[o].pv+=1,-1===e[o].ips.indexOf(t.ip)&&e[o].ips.push(t.ip)}));var o=[],r=[];return t.forEach((function(t){o.push(e[t].pv),r.push(e[t].ips.length)})),{pv:o,uv:r}}},c8bb:function(t,n,e){t.exports=e("54a1")},d2d5:function(t,n,e){e("1654"),e("549b"),t.exports=e("584a").Array.from},da71:function(t,n,e){"use strict";e.d(n,"a",(function(){return i})),e.d(n,"c",(function(){return r})),e.d(n,"b",(function(){return a})),e.d(n,"d",(function(){return s}));var o=e("b775");function i(){return Object(o["a"])({url:"/v1/config",method:"get"})}function r(t){return Object(o["a"])({url:"/v1/config/landing-hosts",method:"patch",data:t})}function a(t){return Object(o["a"])({url:"/v1/config/id-length",method:"patch",data:t})}function s(t){return Object(o["a"])({url:"/v1/config/short-link-404-handling",method:"patch",data:t})}},f410:function(t,n,e){e("1af6"),t.exports=e("584a").Array.isArray},f8a7:function(t,n,e){"use strict";var o=e("acf4"),i=e.n(o);i.a}}]);
\ No newline at end of file
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-7f8ff64d"],{"14c9":function(t,n,e){"use strict";var o=function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("div",{class:t.className,style:{height:t.height,width:t.width}})},i=[],r=e("313e"),a=e.n(r);e("817d");var s={props:{className:{type:String,default:"chart"},width:{type:String,default:"100%"},height:{type:String,default:"350px"},autoResize:{type:Boolean,default:!0},chartData:{type:Object,required:!0},title:{type:Object,default:{}}},data:function(){return{chart:null}},watch:{chartData:{deep:!0,handler:function(t){this.setOptions(t)}}},mounted:function(){var t=this;this.$nextTick((function(){t.initChart()}))},beforeDestroy:function(){this.chart&&(this.chart.dispose(),this.chart=null)},methods:{initChart:function(){this.chart=a.a.init(this.$el,"macarons"),this.setOptions(this.chartData)},setOptions:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.pv,e=t.uv,o=t.dates;this.chart&&this.chart.setOption({title:this.title,xAxis:{data:o,boundaryGap:!1,axisTick:{show:!1}},grid:{left:50,right:50,bottom:20,top:30,containLabel:!0},tooltip:{trigger:"axis",axisPointer:{type:"cross"},padding:[5,10]},yAxis:{axisTick:{show:!1}},legend:{data:["PV","UV"]},series:[{name:"PV",itemStyle:{normal:{color:"#FF005A",lineStyle:{color:"#FF005A",width:2}}},smooth:!0,type:"line",data:n,animationDuration:2800,animationEasing:"cubicInOut"},{name:"UV",smooth:!0,type:"line",itemStyle:{normal:{color:"#3888fa",lineStyle:{color:"#3888fa",width:2},areaStyle:{color:"#f3f8ff"}}},data:e,animationDuration:2800,animationEasing:"quadraticOut"}]})}}},l=s,c=e("2877"),u=Object(c["a"])(l,o,i,!1,null,null,null);n["a"]=u.exports},"1af6":function(t,n,e){var o=e("63b6");o(o.S,"Array",{isArray:e("9003")})},"549b":function(t,n,e){"use strict";var o=e("d864"),i=e("63b6"),r=e("241e"),a=e("b0dc"),s=e("3702"),l=e("b447"),c=e("20fd"),u=e("7cd6");i(i.S+i.F*!e("4ee1")((function(t){Array.from(t)})),"Array",{from:function(t){var n,e,i,d,f=r(t),h="function"==typeof this?this:Array,m=arguments.length,v=m>1?arguments[1]:void 0,g=void 0!==v,p=0,b=u(f);if(g&&(v=o(v,m>2?arguments[2]:void 0,2)),void 0==b||h==Array&&s(b))for(n=l(f.length),e=new h(n);n>p;p++)c(e,p,g?v(f[p],p):f[p]);else for(d=b.call(f),e=new h;!(i=d.next()).done;p++)c(e,p,g?a(d,v,[i.value,p],!0):i.value);return e.length=p,e}})},"54a1":function(t,n,e){e("6c1c"),e("1654"),t.exports=e("95d5")},"774e":function(t,n,e){t.exports=e("d2d5")},9406:function(t,n,e){"use strict";e.r(n);var o=function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("el-main",[e("el-row",{directives:[{name:"show",rawName:"v-show",value:t.pinned.length>0,expression:"pinned.length > 0"}],attrs:{gutter:5}},[e("h3",{staticStyle:{color:"#555"}},[t._v("Pin")]),t._v(" "),t._l(t.pinned,(function(n,o){return e("el-col",{attrs:{span:8}},[e("line-chart",{attrs:{title:{text:n,align:"right"},"chart-data":{pv:t.pinnedLinksData.perDayPvUv[n].pv,uv:t.pinnedLinksData.perDayPvUv[n].uv,dates:t.pinnedLinksData.dates},height:"200px"}})],1)}))],2),t._v(" "),t.pinned.length>0?e("el-divider"):t._e(),t._v(" "),e("el-row",{attrs:{gutter:20}},[e("h3",{staticStyle:{color:"#555"}},[t._v("系统设置")]),t._v(" "),e("el-col",{attrs:{span:7}},[e("el-card",[e("div",{staticClass:"clearfix",attrs:{slot:"header"},slot:"header"},[e("span",[t._v("短链接域名\n "),e("el-popover",{attrs:{placement:"bottom",width:"300",trigger:"hover"}},[e("p",[t._v("\n 配置短链接域名后,可以在短链接列表快速拷贝完整的短链接。"),e("br"),t._v("\n 示例:http://t.anmuji.com/"),e("br"),t._v(" "),e("strong",[t._v('注意:以 "/" 结尾。')])]),t._v(" "),e("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})])],1),t._v(" "),e("div",{directives:[{name:"show",rawName:"v-show",value:2===t.role,expression:"role === 2"}],staticStyle:{float:"right"}},[e("el-button",{attrs:{icon:"el-icon-refresh",size:"mini",circle:""},on:{click:function(n){return t.getConfig("landingHostsForm")}}}),t._v(" "),e("el-button",{attrs:{icon:"el-icon-plus",size:"mini",circle:""},on:{click:function(n){return t.addLandingHost()}}}),t._v(" "),e("el-button",{attrs:{icon:"el-icon-check",size:"mini",circle:""},on:{click:function(n){return t.updateLadingHosts()}}})],1)]),t._v(" "),e("el-form",{ref:"landingHostsForm",attrs:{model:t.landingHostsForm,"label-position":"left","label-width":"0px",size:"mini"}},t._l(t.landingHostsForm.hosts,(function(n,o){return e("el-form-item",{key:n.key,attrs:{prop:"hosts."+o+".value",rules:t.landingHostRules}},[e("el-input",{staticStyle:{width:"90%"},attrs:{readonly:2!==t.role,placeholder:"示例:http://anmuji.com/t/ 以 / 结尾"},model:{value:n.value,callback:function(e){t.$set(n,"value",e)},expression:"host.value"}}),t._v(" "),e("el-button",{directives:[{name:"show",rawName:"v-show",value:t.landingHostsForm.hosts.length>1&&2===t.role,expression:"landingHostsForm.hosts.length > 1 && role === 2"}],staticStyle:{padding:"1px"},attrs:{icon:"el-icon-minus",size:"mini",type:"danger",circle:""},on:{click:function(n){return t.removeLandingHost(o)}}})],1)})),1)],1)],1),t._v(" "),e("el-col",{attrs:{span:10}},[e("el-card",[e("div",{staticClass:"clearfix",attrs:{slot:"header"},slot:"header"},[e("span",[t._v("随机 ID 长度设置\n "),e("el-popover",{attrs:{placement:"bottom",width:"300",trigger:"hover"}},[e("p",[t._v("默认长度即随机生成 ID 的长度,"),e("br"),t._v("最小长度 <= 默认长度 <= 最大长度")]),t._v(" "),e("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})])],1),t._v(" "),e("div",{directives:[{name:"show",rawName:"v-show",value:2===t.role,expression:"role === 2"}],staticStyle:{float:"right"}},[e("el-button",{attrs:{icon:"el-icon-refresh",size:"mini",circle:""},on:{click:function(n){return t.getConfig("idConfigForm")}}}),t._v(" "),e("el-button",{attrs:{icon:"el-icon-check",size:"mini",circle:""},on:{click:function(n){return t.updateIdLengthConfig()}}})],1)]),t._v(" "),e("el-form",{ref:"idConfigForm",attrs:{model:t.idConfigForm,size:"mini","label-position":"top",inline:!0}},[e("el-form-item",{attrs:{prop:"idMinimumLength",label:"最小长度"}},[e("el-input-number",{attrs:{size:"mini",disabled:2!==t.role},model:{value:t.idConfigForm.idMinimumLength,callback:function(n){t.$set(t.idConfigForm,"idMinimumLength",n)},expression:"idConfigForm.idMinimumLength"}})],1),t._v(" "),e("el-form-item",{attrs:{prop:"idLength",label:"默认长度"}},[e("el-input-number",{attrs:{size:"mini",disabled:2!==t.role},model:{value:t.idConfigForm.idLength,callback:function(n){t.$set(t.idConfigForm,"idLength",n)},expression:"idConfigForm.idLength"}})],1),t._v(" "),e("el-form-item",{attrs:{prop:"idMaximumLength",label:"最大长度"}},[e("el-input-number",{attrs:{size:"mini",disabled:2!==t.role},model:{value:t.idConfigForm.idMaximumLength,callback:function(n){t.$set(t.idConfigForm,"idMaximumLength",n)},expression:"idConfigForm.idMaximumLength"}})],1)],1)],1)],1),t._v(" "),e("el-col",{attrs:{span:7}},[e("el-card",[e("div",{staticClass:"clearfix",attrs:{slot:"header"},slot:"header"},[e("span",[t._v("短链接 404 处理\n "),e("el-popover",{attrs:{placement:"bottom",width:"320",trigger:"hover"}},[e("p",[t._v("展示文案:当访问的短链接找不到时,展示设定的文案")]),t._v(" "),e("p",[t._v("URL跳转:当访问的短链接找不到时,跳转到设定的URL")]),t._v(" "),e("i",{staticClass:"el-icon-question",attrs:{slot:"reference"},slot:"reference"})])],1),t._v(" "),e("div",{directives:[{name:"show",rawName:"v-show",value:2===t.role,expression:"role === 2"}],staticStyle:{float:"right"}},[e("el-button",{attrs:{icon:"el-icon-refresh",size:"mini",circle:""},on:{click:function(n){return t.getConfig("shortLinkNotFoundConfigForm")}}}),t._v(" "),e("el-button",{attrs:{icon:"el-icon-check",size:"mini",circle:""},on:{click:function(n){return t.updateShortLinkNotFoundConfig()}}})],1)]),t._v(" "),e("el-form",{ref:"shortLinkNotFoundConfigForm",attrs:{model:t.shortLinkNotFoundConfigForm,size:"mini","label-position":"top"}},[e("el-form-item",{attrs:{prop:"mode",label:"模式"}},[e("el-select",{attrs:{placeholder:"请选择",disabled:2!==t.role},model:{value:t.shortLinkNotFoundConfigForm.mode,callback:function(n){t.$set(t.shortLinkNotFoundConfigForm,"mode",n)},expression:"shortLinkNotFoundConfigForm.mode"}},t._l(t.shortLinkNotFoundModeOptions,(function(t){return e("el-option",{key:t.value,attrs:{label:t.label,value:t.value}})})),1)],1),t._v(" "),e("el-form-item",{directives:[{name:"show",rawName:"v-show",value:"content"===t.shortLinkNotFoundConfigForm.mode,expression:"shortLinkNotFoundConfigForm.mode === 'content'"}],attrs:{prop:"value",label:"文案",rules:t.shortLinkNotFoundConfigRules}},[e("el-input",{attrs:{type:"textarea",placeholder:"你访问的页面不存在哦",readonly:2!==t.role},model:{value:t.shortLinkNotFoundConfigForm.value,callback:function(n){t.$set(t.shortLinkNotFoundConfigForm,"value",n)},expression:"shortLinkNotFoundConfigForm.value"}})],1),t._v(" "),e("el-form-item",{directives:[{name:"show",rawName:"v-show",value:"redirect"===t.shortLinkNotFoundConfigForm.mode,expression:"shortLinkNotFoundConfigForm.mode === 'redirect'"}],attrs:{prop:"value",label:"URL",rules:t.shortLinkNotFoundConfigRules}},[e("el-input",{attrs:{placeholder:"示例:https://github.com/jwma/jump-jump"},model:{value:t.shortLinkNotFoundConfigForm.value,callback:function(n){t.$set(t.shortLinkNotFoundConfigForm,"value",n)},expression:"shortLinkNotFoundConfigForm.value"}})],1)],1)],1)],1)],1)],1)},i=[],r=e("a745"),a=e.n(r);function s(t){if(a()(t)){for(var n=0,e=new Array(t.length);n0){var n=Object(L["b"])(7);this.pinnedLinksData.dates=n.dates,this.pinned.forEach((function(e,o){t.$set(t.pinnedLinksData.perDayPvUv,e,{pv:[],uv:[]}),t.getRequestHistoriesByDateRange(e,n.startDate.format("YYYY-MM-DD"),n.endDate.format("YYYY-MM-DD"))}))}},methods:{getConfig:function(t){var n=this;Object(g["a"])().then((function(e){"landingHostsForm"!==t&&"all"!==t||(n.landingHostsForm.hosts=[],e.data.config.landingHosts.forEach((function(t,e){n.landingHostsForm.hosts.push({value:t,key:Date.now()+e})})),0===e.data.config.landingHosts.length&&n.addLandingHost()),"idConfigForm"!==t&&"all"!==t||(n.idConfigForm.idMinimumLength=e.data.config.idConfig.idMinimumLength,n.idConfigForm.idLength=e.data.config.idConfig.idLength,n.idConfigForm.idMaximumLength=e.data.config.idConfig.idMaximumLength),"shortLinkNotFoundConfigForm"!==t&&"all"!==t||(n.shortLinkNotFoundConfigForm.mode=e.data.config.shortLinkNotFoundConfig.mode,n.shortLinkNotFoundConfigForm.value=e.data.config.shortLinkNotFoundConfig.value)}))},addLandingHost:function(){this.landingHostsForm.hosts.push({value:"",key:Date.now()})},removeLandingHost:function(t){this.landingHostsForm.hosts.splice(t,1)},updateLadingHosts:function(){var t=this;this.$refs["landingHostsForm"].validate((function(n){if(!n)return!1;var e=[];t.landingHostsForm.hosts.forEach((function(t){e.push(t.value)})),Object(g["c"])({hosts:e}).then((function(n){t.$notify({title:"更新成功",message:"成功更新短链接域名",type:"success"})}))}))},updateIdLengthConfig:function(){var t=this;Object(g["b"])(this.idConfigForm).then((function(n){t.$notify({title:"更新成功",message:"成功更新随机 ID 长度",type:"success"})}))},updateShortLinkNotFoundConfig:function(){var t=this;this.$refs["shortLinkNotFoundConfigForm"].validate((function(n){if(!n)return!1;Object(g["d"])(t.shortLinkNotFoundConfigForm).then((function(n){t.$notify({title:"更新成功",message:"短链接 404 处理配置",type:"success"})}))}))},getRequestHistoriesByDateRange:function(t,n,e){var o=this;Object(k["d"])(t,n,e).then((function(n){var e,i;o.list=n.data.histories;var r=Object(L["a"])(o.pinnedLinksData.dates,n.data.histories);(e=o.pinnedLinksData.perDayPvUv[t].pv).push.apply(e,m(r.pv)),(i=o.pinnedLinksData.perDayPvUv[t].uv).push.apply(i,m(r.uv))}))}}},y=C,w=(e("f8a7"),e("2877")),x=Object(w["a"])(y,o,i,!1,null,null,null);n["default"]=x.exports},"95d5":function(t,n,e){var o=e("40c3"),i=e("5168")("iterator"),r=e("481b");t.exports=e("584a").isIterable=function(t){var n=Object(t);return void 0!==n[i]||"@@iterator"in n||r.hasOwnProperty(o(n))}},a745:function(t,n,e){t.exports=e("f410")},acf4:function(t,n,e){},bfad:function(t,n,e){"use strict";e.d(n,"c",(function(){return i})),e.d(n,"b",(function(){return r})),e.d(n,"a",(function(){return a})),e.d(n,"e",(function(){return s})),e.d(n,"f",(function(){return l})),e.d(n,"d",(function(){return c}));var o=e("b775");function i(t){return Object(o["a"])({url:"/v1/short-link/".concat(t),method:"get"})}function r(t,n){return Object(o["a"])({url:"/v1/short-link/?page=".concat(t,"&pageSize=").concat(n),method:"get"})}function a(t){return Object(o["a"])({url:"/v1/short-link/",method:"post",data:t})}function s(t){return Object(o["a"])({url:"/v1/short-link/".concat(t),method:"delete"})}function l(t,n){return Object(o["a"])({url:"/v1/short-link/".concat(t),method:"patch",data:n})}function c(t,n,e){return Object(o["a"])({url:"/v1/short-link/".concat(t,"/data?startDate=").concat(n,"&endDate=").concat(e),method:"get"})}},c3cc:function(t,n,e){"use strict";e.d(n,"b",(function(){return r})),e.d(n,"a",(function(){return a}));e("ac6a");var o=e("c1df"),i=e.n(o);function r(t){var n=i()(),e=n.clone().add(-(t-1),"d"),o=n.clone(),r=e.clone(),a=[];while(r.isSameOrBefore(o))a.push(r.format("YYYY-MM-DD")),r.add(1,"d");return{startDate:e,endDate:o,dates:a}}function a(t,n){var e={};t.forEach((function(t){e[t]={pv:0,ips:[]}})),n.forEach((function(t,n){var o=i()(t.time).format("YYYY-MM-DD");e[o].pv+=1,-1===e[o].ips.indexOf(t.ip)&&e[o].ips.push(t.ip)}));var o=[],r=[];return t.forEach((function(t){o.push(e[t].pv),r.push(e[t].ips.length)})),{pv:o,uv:r}}},c8bb:function(t,n,e){t.exports=e("54a1")},d2d5:function(t,n,e){e("1654"),e("549b"),t.exports=e("584a").Array.from},da71:function(t,n,e){"use strict";e.d(n,"a",(function(){return i})),e.d(n,"c",(function(){return r})),e.d(n,"b",(function(){return a})),e.d(n,"d",(function(){return s}));var o=e("b775");function i(){return Object(o["a"])({url:"/v1/config",method:"get"})}function r(t){return Object(o["a"])({url:"/v1/config/landing-hosts",method:"patch",data:t})}function a(t){return Object(o["a"])({url:"/v1/config/id-length",method:"patch",data:t})}function s(t){return Object(o["a"])({url:"/v1/config/short-link-404-handling",method:"patch",data:t})}},f410:function(t,n,e){e("1af6"),t.exports=e("584a").Array.isArray},f8a7:function(t,n,e){"use strict";var o=e("acf4"),i=e.n(o);i.a}}]);
\ No newline at end of file