From 10580a0d632eaed9d84a1cf6193785a1a39f9687 Mon Sep 17 00:00:00 2001 From: minglipro Date: Sun, 29 Jun 2025 17:52:31 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BC=96=E5=86=99=E4=B8=80=E4=BA=9B=E5=89=8D?= =?UTF-8?q?=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +- application.yaml | 4 +- package.json | 16 +- .../config/MyBatisPlusMetaObjectHandler.java | 49 + .../disk/config/SpringDocConfig.java | 28 +- .../disk/config/StpInterfaceImpl.java | 42 + .../disk/controller/AuthController.java | 6 +- .../disk/controller/IndexController.java | 2 +- .../disk/controller/SystemController.java | 28 + .../com/mingliqiye/disk/dto/system/Info.java | 12 + .../disk/exception/BaseExceptionHandler.java | 43 +- .../java/com/mingliqiye/disk/model/User.java | 13 +- .../com/mingliqiye/disk/util/PanStpUtil.java | 9 +- src/main/resources/application.yaml | 6 +- src/main/resources/sql/users.sql | 24 +- tsconfig.app.json | 16 +- vite.config.ts | 31 +- web-src/App.vue | 86 +- web-src/api/auth.ts | 33 + web-src/api/index.ts | 1 + web-src/api/system.ts | 10 + web-src/assets/SwaggerDark.scss | 1257 +++++++++++++++++ web-src/assets/base.css | 86 -- web-src/assets/index.scss | 141 ++ web-src/assets/{icon.svg => index.svg} | 0 web-src/assets/main.css | 35 - web-src/assets/var.scss | 16 + web-src/components/HelloWorld.vue | 43 - web-src/components/Icon.vue | 41 + web-src/components/TheWelcome.vue | 97 -- web-src/components/WelcomeItem.vue | 87 -- web-src/components/icons/IconCommunity.vue | 6 - .../components/icons/IconDocumentation.vue | 6 - web-src/components/icons/IconEcosystem.vue | 6 - web-src/components/icons/IconSupport.vue | 6 - web-src/components/icons/IconTooling.vue | 17 - web-src/index.html | 8 +- web-src/layout/Head.vue | 175 +++ web-src/layout/Router.vue | 15 + web-src/layout/index.vue | 15 + web-src/main.ts | 7 +- web-src/plugin/alova/index.ts | 47 + web-src/plugin/alova/type.ts | 13 + web-src/plugin/index.ts | 11 + web-src/plugin/router/index.ts | 25 + web-src/plugin/stores/auth.ts | 46 + web-src/plugin/stores/index.ts | 8 + web-src/plugin/stores/setting.ts | 19 + web-src/router/index.ts | 23 - web-src/stores/counter.ts | 12 - web-src/util/Cookies.ts | 57 + web-src/util/UseBoolRef.ts | 25 + web-src/util/index.ts | 2 + web-src/views/AboutView.vue | 15 - web-src/views/HomeView.vue | 15 +- web-src/views/SwaggerView.vue | 18 + 56 files changed, 2275 insertions(+), 589 deletions(-) create mode 100644 src/main/java/com/mingliqiye/disk/config/MyBatisPlusMetaObjectHandler.java create mode 100644 src/main/java/com/mingliqiye/disk/config/StpInterfaceImpl.java create mode 100644 src/main/java/com/mingliqiye/disk/controller/SystemController.java create mode 100644 src/main/java/com/mingliqiye/disk/dto/system/Info.java create mode 100644 web-src/api/auth.ts create mode 100644 web-src/api/index.ts create mode 100644 web-src/api/system.ts create mode 100644 web-src/assets/SwaggerDark.scss delete mode 100644 web-src/assets/base.css create mode 100644 web-src/assets/index.scss rename web-src/assets/{icon.svg => index.svg} (100%) delete mode 100644 web-src/assets/main.css create mode 100644 web-src/assets/var.scss delete mode 100644 web-src/components/HelloWorld.vue create mode 100644 web-src/components/Icon.vue delete mode 100644 web-src/components/TheWelcome.vue delete mode 100644 web-src/components/WelcomeItem.vue delete mode 100644 web-src/components/icons/IconCommunity.vue delete mode 100644 web-src/components/icons/IconDocumentation.vue delete mode 100644 web-src/components/icons/IconEcosystem.vue delete mode 100644 web-src/components/icons/IconSupport.vue delete mode 100644 web-src/components/icons/IconTooling.vue create mode 100644 web-src/layout/Head.vue create mode 100644 web-src/layout/Router.vue create mode 100644 web-src/layout/index.vue create mode 100644 web-src/plugin/alova/index.ts create mode 100644 web-src/plugin/alova/type.ts create mode 100644 web-src/plugin/index.ts create mode 100644 web-src/plugin/router/index.ts create mode 100644 web-src/plugin/stores/auth.ts create mode 100644 web-src/plugin/stores/index.ts create mode 100644 web-src/plugin/stores/setting.ts delete mode 100644 web-src/router/index.ts delete mode 100644 web-src/stores/counter.ts create mode 100644 web-src/util/Cookies.ts create mode 100644 web-src/util/UseBoolRef.ts create mode 100644 web-src/util/index.ts delete mode 100644 web-src/views/AboutView.vue create mode 100644 web-src/views/SwaggerView.vue diff --git a/.gitignore b/.gitignore index 221d5e6..bf46db6 100644 --- a/.gitignore +++ b/.gitignore @@ -16,9 +16,9 @@ build/ bin/ !**/src/main/**/bin/ !**/src/test/**/bin/ +pnpm-workspace.yaml ### IntelliJ IDEA ### -.idea *.iws *.iml *.ipr @@ -41,3 +41,6 @@ pnpm-lock.yaml src/main/resources/html log + +web-src/types +.idea diff --git a/application.yaml b/application.yaml index 15eff44..4a17928 100644 --- a/application.yaml +++ b/application.yaml @@ -1,7 +1,7 @@ config: port: 9963 - app-name: maven-repository - app-version: 1.0 + app-name: pan-disk + app-version: 1.1 data-source: mysql: username: pan diff --git a/package.json b/package.json index 7d98ccf..6d98cd2 100644 --- a/package.json +++ b/package.json @@ -17,27 +17,41 @@ "format": "prettier --write \"**/*.{js,ts,jsx,tsx,cjs,cts,mjs,mts,vue,astro,java}\"" }, "dependencies": { + "@iconify/vue": "^5.0.0", + "@types/vue-router": "^2.0.0", + "@vueuse/core": "^13.4.0", + "naive-ui": "^2.42.0", "pinia": "^3.0.3", + "swagger-ui-dist": "^5.25.3", + "unplugin-auto-import": "^19.3.0", + "unplugin-vue-components": "^28.8.0", "vue": "^3.5.17", "vue-router": "^4.5.1" }, "devDependencies": { "@tsconfig/node22": "^22.0.2", + "@types/js-cookie": "^3.0.6", "@types/node": "^22.15.32", + "@types/swagger-ui-dist": "^3.30.6", "@vitejs/plugin-vue": "^6.0.0", "@vue/eslint-config-prettier": "^10.2.0", "@vue/eslint-config-typescript": "^14.5.1", "@vue/tsconfig": "^0.7.0", + "alova": "^3.3.3", "eslint": "^9.29.0", "eslint-plugin-oxlint": "~1.1.0", "eslint-plugin-vue": "~10.2.0", "jiti": "^2.4.2", + "js-base64": "^3.7.7", + "js-cookie": "^3.0.5", "npm-run-all2": "^8.0.4", "oxlint": "~1.1.0", + "pinia-plugin-persistedstate": "^4.4.0", "prettier": "3.5.3", "prettier-plugin-java": "^2.6.8", + "sass-embedded": "^1.89.2", "typescript": "~5.8.0", - "vite": "npm:rolldown-vite@latest", + "vite": "~6.0.0", "vite-plugin-vue-devtools": "^7.7.7", "vue-tsc": "^2.2.10" } diff --git a/src/main/java/com/mingliqiye/disk/config/MyBatisPlusMetaObjectHandler.java b/src/main/java/com/mingliqiye/disk/config/MyBatisPlusMetaObjectHandler.java new file mode 100644 index 0000000..1fc1fad --- /dev/null +++ b/src/main/java/com/mingliqiye/disk/config/MyBatisPlusMetaObjectHandler.java @@ -0,0 +1,49 @@ +package com.mingliqiye.disk.config; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.mingliqiye.disk.time.DateTime; +import com.mingliqiye.disk.util.PanStpUtil; +import com.mingliqiye.disk.uuid.UUID; +import java.util.Objects; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MyBatisPlusMetaObjectHandler implements MetaObjectHandler { + + private static final String CREATE_USER_ID = "createUserId"; + private static final String CREATE_TIME = "createTime"; + private static final String UPDATE_USER_ID = "updateUserId"; + private static final String UPDATE_TIME = "updateTime"; + private static final UUID SYSTEM_ID_UUID = UUID.ofString("48126760-5483-11F0-B90C-6D1CD960F6F3"); + + @Override + public void insertFill(MetaObject metaObject) { + if (metaObject.hasSetter(CREATE_USER_ID)) { + this.strictInsertFill( + metaObject, + CREATE_USER_ID, + UUID.class, + Objects.requireNonNullElse(PanStpUtil.getLoginIdDefaultNull(), SYSTEM_ID_UUID) + ); + } + if (metaObject.hasSetter(CREATE_TIME)) { + this.strictInsertFill(metaObject, CREATE_TIME, DateTime.class, DateTime.now()); + } + } + + @Override + public void updateFill(MetaObject metaObject) { + if (metaObject.hasSetter(UPDATE_USER_ID)) { + this.strictUpdateFill( + metaObject, + UPDATE_USER_ID, + UUID.class, + Objects.requireNonNullElse(PanStpUtil.getLoginIdDefaultNull(), SYSTEM_ID_UUID) + ); + } + if (metaObject.hasSetter(UPDATE_TIME)) { + this.strictUpdateFill(metaObject, UPDATE_TIME, DateTime.class, DateTime.now()); + } + } +} diff --git a/src/main/java/com/mingliqiye/disk/config/SpringDocConfig.java b/src/main/java/com/mingliqiye/disk/config/SpringDocConfig.java index a847aac..4a6b863 100644 --- a/src/main/java/com/mingliqiye/disk/config/SpringDocConfig.java +++ b/src/main/java/com/mingliqiye/disk/config/SpringDocConfig.java @@ -1,5 +1,6 @@ package com.mingliqiye.disk.config; +import com.mingliqiye.disk.configuration.Config; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; @@ -9,9 +10,13 @@ import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; +import io.swagger.v3.oas.models.servers.Server; +import java.util.List; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +@Slf4j @OpenAPIDefinition( externalDocs = @ExternalDocumentation( description = "@git.mingliqiye", @@ -29,23 +34,36 @@ import org.springframework.context.annotation.Configuration; @Configuration public class SpringDocConfig { + private final Config config; + + public SpringDocConfig(Config config) { + this.config = config; + } + @Bean public OpenAPI openAPI() { + Server server = new Server(); + server.setUrl("/"); + server.setDescription("当前服务"); + Server server2 = new Server(); + server2.setUrl("http://localhost:" + config.getPort() + "/"); + server2.setDescription("本机服务"); return new OpenAPI() // 配置接口文档基本信息 - .info(this.getApiInfo()); + .info(this.getApiInfo()) + .servers(List.of(server, server2)); } private Info getApiInfo() { return new Info() - .title("pan-disk") - .description("SpringBoot3 pan-disk Swagger3 ApiDoc") + .title(config.getAppName()) + .version(config.getAppVersion()) + .description("SpringBoot3 %s-V%s Swagger3 ApiDoc".formatted(config.getAppName(), config.getAppVersion())) .contact( new Contact().name("mingliqiye").url("https://www.mingliqiye.com").email("minglipro@mingliqiye.com") ) .license(new License().name("Apache 2.0").url("https://www.apache.org/licenses/LICENSE-2.0")) .summary("ApiDoc") - .termsOfService("https://pan.mingliqiye.com/") - .version("1.0"); + .termsOfService("https://pan.mingliqiye.com/"); } } diff --git a/src/main/java/com/mingliqiye/disk/config/StpInterfaceImpl.java b/src/main/java/com/mingliqiye/disk/config/StpInterfaceImpl.java new file mode 100644 index 0000000..fe97aeb --- /dev/null +++ b/src/main/java/com/mingliqiye/disk/config/StpInterfaceImpl.java @@ -0,0 +1,42 @@ +package com.mingliqiye.disk.config; + +import cn.dev33.satoken.stp.StpInterface; +import com.mingliqiye.disk.mappers.UserMapper; +import com.mingliqiye.disk.model.User; +import com.mingliqiye.disk.uuid.UUID; +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; + +@Slf4j +@Configuration +public class StpInterfaceImpl implements StpInterface { + + private final UserMapper userMapper; + + public StpInterfaceImpl(UserMapper userMapper) { + this.userMapper = userMapper; + } + + /** + * 返回一个账号所拥有的权限码集合 + */ + @Override + public List getPermissionList(Object loginId, String loginType) { + User user = userMapper.selectById(UUID.ofString((String) loginId)); + List list = new ArrayList<>(user.getPrermissions()); + if (user.isAdmin()) list.add("*.*.*"); + user.getRoles().forEach(i -> list.add(String.format("%s.*.*", i))); + log.info(String.valueOf(list)); + return list; + } + + /** + * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验) + */ + @Override + public List getRoleList(Object loginId, String loginType) { + return userMapper.selectById(UUID.ofString((String) loginId)).getRoles(); + } +} diff --git a/src/main/java/com/mingliqiye/disk/controller/AuthController.java b/src/main/java/com/mingliqiye/disk/controller/AuthController.java index 8622f86..97fa8c7 100644 --- a/src/main/java/com/mingliqiye/disk/controller/AuthController.java +++ b/src/main/java/com/mingliqiye/disk/controller/AuthController.java @@ -4,7 +4,7 @@ import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.stp.StpUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.mingliqiye.disk.dto.auth.Login; -import com.mingliqiye.disk.exception.ExceptionCode; +import com.mingliqiye.disk.exception.InternalServerException; import com.mingliqiye.disk.http.Respose; import com.mingliqiye.disk.mappers.UserMapper; import com.mingliqiye.disk.model.User; @@ -36,7 +36,7 @@ public class AuthController { if (user != null && BCrypt.checkpw(loginBody.getPassword(), user.getPassword())) { return Respose.builder(PanStpUtil.login(user.getId())); } - return Respose.error(String.class, ExceptionCode.ERROR_INTERNAL_SERVER, "用户名或密码错误"); + throw new InternalServerException("用户名或密码错误"); } @Operation(summary = "获取当前登陆用户的信息") @@ -47,8 +47,8 @@ public class AuthController { } @Operation(summary = "登出", security = @SecurityRequirement(name = "Authorization-Bearer-Token")) - @DeleteMapping("/logout") @SaCheckLogin + @DeleteMapping("/logout") public Respose logout() { StpUtil.logout(); return Respose.builder(); diff --git a/src/main/java/com/mingliqiye/disk/controller/IndexController.java b/src/main/java/com/mingliqiye/disk/controller/IndexController.java index c930989..6a1c291 100644 --- a/src/main/java/com/mingliqiye/disk/controller/IndexController.java +++ b/src/main/java/com/mingliqiye/disk/controller/IndexController.java @@ -13,7 +13,7 @@ import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBo @Tag(name = "前端路由", description = "统一匹配路径指向VueRouter") public class IndexController { - @GetMapping(value = { "/", "/{path:^(?!static|apis).*$}/**" }) + @GetMapping(value = { "/", "/{path:^(?!static|apis|blob).*$}/**" }) public ResponseEntity index() { StreamingResponseBody streamingResponseBody = s -> { try (InputStream stream = this.getClass().getResourceAsStream("/html/index.html")) { diff --git a/src/main/java/com/mingliqiye/disk/controller/SystemController.java b/src/main/java/com/mingliqiye/disk/controller/SystemController.java new file mode 100644 index 0000000..44b1428 --- /dev/null +++ b/src/main/java/com/mingliqiye/disk/controller/SystemController.java @@ -0,0 +1,28 @@ +package com.mingliqiye.disk.controller; + +import com.mingliqiye.disk.configuration.Config; +import com.mingliqiye.disk.dto.system.Info; +import com.mingliqiye.disk.http.Respose; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/apis/system") +@Tag(name = "系统路由", description = "访问系统的一些功能") +public class SystemController { + + private final Config config; + + public SystemController(Config config) { + this.config = config; + } + + @Operation(summary = "系统信息") + @GetMapping("/info") + public Respose info() { + return Respose.builder(new Info(config.getAppName(), config.getAppVersion())); + } +} diff --git a/src/main/java/com/mingliqiye/disk/dto/system/Info.java b/src/main/java/com/mingliqiye/disk/dto/system/Info.java new file mode 100644 index 0000000..9f3b5e0 --- /dev/null +++ b/src/main/java/com/mingliqiye/disk/dto/system/Info.java @@ -0,0 +1,12 @@ +package com.mingliqiye.disk.dto.system; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class Info { + + private String appName; + private String appVersion; +} diff --git a/src/main/java/com/mingliqiye/disk/exception/BaseExceptionHandler.java b/src/main/java/com/mingliqiye/disk/exception/BaseExceptionHandler.java index 16b863b..02ea19d 100644 --- a/src/main/java/com/mingliqiye/disk/exception/BaseExceptionHandler.java +++ b/src/main/java/com/mingliqiye/disk/exception/BaseExceptionHandler.java @@ -6,7 +6,6 @@ import cn.dev33.satoken.exception.NotRoleException; import com.mingliqiye.disk.http.Respose; import com.mingliqiye.disk.util.StringUtil; import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.http.HttpStatus; @@ -23,25 +22,21 @@ import org.springframework.web.servlet.NoHandlerFoundException; public class BaseExceptionHandler { @ExceptionHandler(BaseException.class) - public ResponseEntity> exceptionHandler(BaseException e, HttpServletRequest request) { + public ResponseEntity> exceptionHandler(BaseException e) { return ResponseEntity.status(e.getCode()).body( Respose.builder().setCode(e.getCode()).setMessage(StringUtil.format("{}", e.getMessage())) ); } @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - public Respose exceptionHandler(HttpRequestMethodNotSupportedException e, HttpServletRequest request) { + public Respose exceptionHandler(HttpRequestMethodNotSupportedException e) { return Respose.builder() .setCode(ExceptionCode.ERROR_METHOD_NOT_ALLOWED.getValue()) .setMessage(StringUtil.format("{} by {}", e.getMessage(), e.getClass().getName())); } @ExceptionHandler(NoHandlerFoundException.class) - public ResponseEntity> exceptionHandler( - NoHandlerFoundException e, - HttpServletRequest request, - HttpServletResponse response - ) { + public ResponseEntity> exceptionHandler(NoHandlerFoundException e) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body( Respose.builder() .setCode(ExceptionCode.ERROR_NOT_FOUND.getValue()) @@ -50,26 +45,30 @@ public class BaseExceptionHandler { } @ExceptionHandler(NotLoginException.class) - public Respose exceptionHandler(NotLoginException e, HttpServletRequest request) { - return Respose.builder() - .setCode(ExceptionCode.ERROR_UNAUTHORIZED.getValue()) - .setMessage(e.getMessage()) - .setData(e.getType()); + public ResponseEntity> exceptionHandler(NotLoginException e, HttpServletRequest request) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body( + Respose.builder() + .setCode(ExceptionCode.ERROR_UNAUTHORIZED.getValue()) + .setMessage(e.getMessage()) + .setData(e.getType()) + ); } @ExceptionHandler(HttpMessageNotReadableException.class) - public Respose exceptionHandler(HttpMessageNotReadableException e, HttpServletRequest request) { - return Respose.builder() - .setCode(ExceptionCode.ERROR_FORBIDDEN.getValue()) - .setMessage(StringUtil.format("{} by {}", e.getMessage(), e.getClass().getName())); + public ResponseEntity> exceptionHandler(HttpMessageNotReadableException e) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body( + Respose.builder().setCode(ExceptionCode.ERROR_FORBIDDEN.getValue()).setMessage(e.getMessage()) + ); } @ExceptionHandler(NotRoleException.class) - public Respose exceptionHandler(NotRoleException e) { - return Respose.builder() - .setCode(ExceptionCode.ERROR_FORBIDDEN.getValue()) - .setMessage(e.getMessage()) - .setData(e.getCode()); + public ResponseEntity> exceptionHandler(NotRoleException e) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body( + Respose.builder() + .setCode(ExceptionCode.ERROR_FORBIDDEN.getValue()) + .setMessage(e.getMessage()) + .setData(e.getCode()) + ); } @ExceptionHandler(NotPermissionException.class) diff --git a/src/main/java/com/mingliqiye/disk/model/User.java b/src/main/java/com/mingliqiye/disk/model/User.java index 128574f..0b04e39 100644 --- a/src/main/java/com/mingliqiye/disk/model/User.java +++ b/src/main/java/com/mingliqiye/disk/model/User.java @@ -1,5 +1,6 @@ package com.mingliqiye.disk.model; +import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; @@ -32,7 +33,17 @@ public class User { private byte[] icon; private boolean admin; - private DateTime creationTime; + + @TableField(fill = FieldFill.INSERT) + private UUID createUserId; + + @TableField(fill = FieldFill.INSERT) + private DateTime createTime; + + @TableField(fill = FieldFill.INSERT_UPDATE) + private UUID updateUserId; + + @TableField(fill = FieldFill.INSERT_UPDATE) private DateTime updateTime; public User setPasswordNull() { diff --git a/src/main/java/com/mingliqiye/disk/util/PanStpUtil.java b/src/main/java/com/mingliqiye/disk/util/PanStpUtil.java index a3d4822..febaaeb 100644 --- a/src/main/java/com/mingliqiye/disk/util/PanStpUtil.java +++ b/src/main/java/com/mingliqiye/disk/util/PanStpUtil.java @@ -2,6 +2,8 @@ package com.mingliqiye.disk.util; import cn.dev33.satoken.stp.StpUtil; import com.mingliqiye.disk.uuid.UUID; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class PanStpUtil { @@ -9,7 +11,12 @@ public class PanStpUtil { return UUID.ofString((String) StpUtil.getLoginId()); } - public static String login(UUID uuid) { + @Nullable + public static UUID getLoginIdDefaultNull() { + return UUID.ofString((String) StpUtil.getLoginId()); + } + + public static String login(@NotNull UUID uuid) { StpUtil.login(uuid.toUUIDString()); return StpUtil.getTokenValue(); } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 4dfa7e7..fe77836 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,7 +1,7 @@ config: port: 9963 - app-name: maven-repository - app-version: 1.0 + app-name: pan-disk + app-version: 1.1 data-source: mysql: username: pan @@ -85,6 +85,6 @@ mybatis-plus: springdoc: swagger-ui: - path: /apis/swagger + enabled: false api-docs: path: /apis/swagger/api.json diff --git a/src/main/resources/sql/users.sql b/src/main/resources/sql/users.sql index bb316f9..27c695b 100644 --- a/src/main/resources/sql/users.sql +++ b/src/main/resources/sql/users.sql @@ -4,15 +4,25 @@ create table `users` id binary(16) default (uuid_to_bin( uuid(), 1)) primary key, - username varchar(256) unique not null, - password varchar(128) not null, - nickname varchar(256) not null, + username varchar(256) unique not null, + password varchar(128) not null, + nickname varchar(256) not null, prermissions json, roles json, icon mediumblob, admin bool default false, - creation_time timestamp(6) default current_timestamp(6) not null, - update_time timestamp(6) null + create_user_id binary(16) not null, + create_time timestamp(6) default now(6) not null, + update_user_id binary(16) null, + update_time timestamp(6) default now(6), + constraint foreign key (create_user_id) references users (id), + constraint foreign key (update_user_id) references users (id) + ); -INSERT INTO users (id, username, password, nickname, prermissions, roles, icon, admin) -VALUES (0x689EFC204D1F11F08134DB0063E177A7, 'admin', 'admin', '管理员', '[]', '[]', null, 1); +INSERT INTO users (id, username, password, nickname, prermissions, roles, icon, admin, create_user_id) +VALUES (0x48126760548311F0B90C6D1CD960F6F3, 'system', 'system', '系统', '[]', '[]', null, 1, + 0x48126760548311F0B90C6D1CD960F6F3); +INSERT INTO users (id, username, password, nickname, prermissions, roles, icon, admin, create_user_id) +VALUES (0x689EFC204D1F11F08134DB0063E177A7, 'admin', '$2a$10$ti.W.FpQobTaW7eTTmHYJOuBS68uPP0Ikkw33UTCJSgcNhg0AGy7a', + '管理员', '[]', '[]', null, 1, + 0x48126760548311F0B90C6D1CD960F6F3); diff --git a/tsconfig.app.json b/tsconfig.app.json index 280fb25..41b1eae 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -1,12 +1,20 @@ { "extends": "@vue/tsconfig/tsconfig.dom.json", - "include": ["env.d.ts", "web-src/**/*", "web-src/**/*.vue"], - "exclude": ["web-src/**/__tests__/*"], + "include": [ + "env.d.ts", + "web-src/**/*", + "web-src/**/*.vue", + "web-src/types/**/*.d.ts" + ], + "exclude": [ + "web-src/**/__tests__/*" + ], "compilerOptions": { "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", - "paths": { - "@/*": ["./web-src/*"] + "@/*": [ + "./web-src/*" + ] } } } diff --git a/vite.config.ts b/vite.config.ts index 6c6a4ab..4a575c6 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,11 +2,32 @@ import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import vueDevTools from 'vite-plugin-vue-devtools'; import path from 'node:path'; +import AutoImport from 'unplugin-auto-import/vite'; +import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'; +import Components from 'unplugin-vue-components/vite'; -// https://vite.dev/config/ export default defineConfig({ root: path.resolve(__dirname, 'web-src'), - plugins: [vue(), vueDevTools()], + plugins: [ + vue(), + vueDevTools(), + AutoImport({ + imports: [ + 'vue', + '@vueuse/core', + 'pinia', + 'vue-router', + { + 'naive-ui': ['useDialog', 'useMessage', 'useNotification', 'useLoadingBar'], + }, + ], + dts: 'types/AutoImport.d.ts', + }), + Components({ + resolvers: [NaiveUiResolver()], + dts: 'types/Components.d.ts', + }), + ], resolve: { alias: { '@': path.resolve(__dirname, 'web-src'), @@ -23,4 +44,10 @@ export default defineConfig({ }, }, }, + server: { + host: '0.0.0.0', + proxy: { + '/apis': 'http://localhost:9963', + }, + }, }); diff --git a/web-src/App.vue b/web-src/App.vue index ad73374..b221b97 100644 --- a/web-src/App.vue +++ b/web-src/App.vue @@ -1,85 +1,7 @@ - - - + diff --git a/web-src/api/auth.ts b/web-src/api/auth.ts new file mode 100644 index 0000000..6d169b8 --- /dev/null +++ b/web-src/api/auth.ts @@ -0,0 +1,33 @@ +import { alovaInstance, type AlovaResponseType } from '@/plugin'; + +export function login(data: loginDtoBody) { + return alovaInstance.Post>('/apis/auth/login', data); +} + +export function woIsMe() { + return alovaInstance.Get>('apis/auth/who-is-me'); +} + +export function logout() { + return alovaInstance.Delete('apis/auth/logout'); +} + +export interface loginDtoBody { + username: string; + password: string; +} + +export interface UserDto { + id: string; + username: string; + password: string; + nickname: string; + prermissions: string[]; + roles: string[]; + icon: string; + admin: boolean; + createUserId: string; + createTime: string; + updateUserId: string; + updateTime: string; +} diff --git a/web-src/api/index.ts b/web-src/api/index.ts new file mode 100644 index 0000000..269586e --- /dev/null +++ b/web-src/api/index.ts @@ -0,0 +1 @@ +export * from './auth'; diff --git a/web-src/api/system.ts b/web-src/api/system.ts new file mode 100644 index 0000000..70a3307 --- /dev/null +++ b/web-src/api/system.ts @@ -0,0 +1,10 @@ +import { alovaInstance, type AlovaResponseType } from '@/plugin'; + +export function getSysInfo() { + return alovaInstance.Get>('apis/system/info'); +} + +export interface SysInfo { + appName: string; + appVersion: string; +} diff --git a/web-src/assets/SwaggerDark.scss b/web-src/assets/SwaggerDark.scss new file mode 100644 index 0000000..61f94ee --- /dev/null +++ b/web-src/assets/SwaggerDark.scss @@ -0,0 +1,1257 @@ +html.dark { + + a { + color: #8c8cfa; + } + + embed[type="application/pdf"] { + filter: invert(90%); + } + + html { + background: #1f1f1f !important; + box-sizing: border-box; + filter: contrast(100%) brightness(100%) saturate(100%); + overflow-y: scroll; + } + + body { + background: #1f1f1f; + background-color: #1f1f1f; + background-image: none !important; + } + + button, input, select, textarea { + background-color: #1f1f1f; + color: #bfbfbf; + } + + font, html { + color: #bfbfbf; + } + + .swagger-ui, .swagger-ui section h3 { + color: #b5bac9; + } + + .swagger-ui a { + background-color: transparent; + } + + .swagger-ui mark { + background-color: #664b00; + color: #bfbfbf; + } + + .swagger-ui legend { + color: inherit; + } + + .swagger-ui .debug * { + outline: #e6da99 solid 1px; + } + + .swagger-ui .debug-white * { + outline: #fff solid 1px; + } + + .swagger-ui .debug-black * { + outline: #bfbfbf solid 1px; + } + + .swagger-ui .debug-grid { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTRDOTY4N0U2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTRDOTY4N0Q2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3NjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3NzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsBS+GMAAAAjSURBVHjaYvz//z8DLsD4gcGXiYEAGBIKGBne//fFpwAgwAB98AaF2pjlUQAAAABJRU5ErkJggg==) 0 0; + } + + .swagger-ui .debug-grid-16 { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODYyRjhERDU2N0YyMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODYyRjhERDQ2N0YyMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QTY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3QjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvCS01IAAABMSURBVHjaYmR4/5+BFPBfAMFm/MBgx8RAGWCn1AAmSg34Q6kBDKMGMDCwICeMIemF/5QawEipAWwUhwEjMDvbAWlWkvVBwu8vQIABAEwBCph8U6c0AAAAAElFTkSuQmCC) 0 0; + } + + .swagger-ui .debug-grid-8-solid { + background: url(data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAAAAAD/4QMxaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzExMSA3OS4xNTgzMjUsIDIwMTUvMDkvMTAtMDE6MTA6MjAgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1IChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkIxMjI0OTczNjdCMzExRTZCMkJDRTI0MDgxMDAyMTcxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkIxMjI0OTc0NjdCMzExRTZCMkJDRTI0MDgxMDAyMTcxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QjEyMjQ5NzE2N0IzMTFFNkIyQkNFMjQwODEwMDIxNzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QjEyMjQ5NzI2N0IzMTFFNkIyQkNFMjQwODEwMDIxNzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAbGhopHSlBJiZBQi8vL0JHPz4+P0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHAR0pKTQmND8oKD9HPzU/R0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0f/wAARCAAIAAgDASIAAhEBAxEB/8QAWQABAQAAAAAAAAAAAAAAAAAAAAYBAQEAAAAAAAAAAAAAAAAAAAIEEAEBAAMBAAAAAAAAAAAAAAABADECA0ERAAEDBQAAAAAAAAAAAAAAAAARITFBUWESIv/aAAwDAQACEQMRAD8AoOnTV1QTD7JJshP3vSM3P//Z) 0 0 #1c1c21; + } + + .swagger-ui .debug-grid-16-solid { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzY3MkJEN0U2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzY3MkJEN0Y2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3RDY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pve6J3kAAAAzSURBVHjaYvz//z8D0UDsMwMjSRoYP5Gq4SPNbRjVMEQ1fCRDg+in/6+J1AJUxsgAEGAA31BAJMS0GYEAAAAASUVORK5CYII=) 0 0 #1c1c21; + } + + .swagger-ui .b--black { + border-color: #000; + } + + .swagger-ui .b--near-black { + border-color: #121212; + } + + .swagger-ui .b--dark-gray { + border-color: #333; + } + + .swagger-ui .b--mid-gray { + border-color: #545454; + } + + .swagger-ui .b--gray { + border-color: #787878; + } + + .swagger-ui .b--silver { + border-color: #999; + } + + .swagger-ui .b--light-silver { + border-color: #6e6e6e; + } + + .swagger-ui .b--moon-gray { + border-color: #4d4d4d; + } + + .swagger-ui .b--light-gray { + border-color: #2b2b2b; + } + + .swagger-ui .b--near-white { + border-color: #242424; + } + + .swagger-ui .b--white { + border-color: #1c1c21; + } + + .swagger-ui .b--white-90 { + border-color: rgba(28, 28, 33, .9); + } + + .swagger-ui .b--white-80 { + border-color: rgba(28, 28, 33, .8); + } + + .swagger-ui .b--white-70 { + border-color: rgba(28, 28, 33, .7); + } + + .swagger-ui .b--white-60 { + border-color: rgba(28, 28, 33, .6); + } + + .swagger-ui .b--white-50 { + border-color: rgba(28, 28, 33, .5); + } + + .swagger-ui .b--white-40 { + border-color: rgba(28, 28, 33, .4); + } + + .swagger-ui .b--white-30 { + border-color: rgba(28, 28, 33, .3); + } + + .swagger-ui .b--white-20 { + border-color: rgba(28, 28, 33, .2); + } + + .swagger-ui .b--white-10 { + border-color: rgba(28, 28, 33, .1); + } + + .swagger-ui .b--white-05 { + border-color: rgba(28, 28, 33, .05); + } + + .swagger-ui .b--white-025 { + border-color: rgba(28, 28, 33, .024); + } + + .swagger-ui .b--white-0125 { + border-color: rgba(28, 28, 33, .01); + } + + .swagger-ui .b--black-90 { + border-color: rgba(0, 0, 0, .9); + } + + .swagger-ui .b--black-80 { + border-color: rgba(0, 0, 0, .8); + } + + .swagger-ui .b--black-70 { + border-color: rgba(0, 0, 0, .7); + } + + .swagger-ui .b--black-60 { + border-color: rgba(0, 0, 0, .6); + } + + .swagger-ui .b--black-50 { + border-color: rgba(0, 0, 0, .5); + } + + .swagger-ui .b--black-40 { + border-color: rgba(0, 0, 0, .4); + } + + .swagger-ui .b--black-30 { + border-color: rgba(0, 0, 0, .3); + } + + .swagger-ui .b--black-20 { + border-color: rgba(0, 0, 0, .2); + } + + .swagger-ui .b--black-10 { + border-color: rgba(0, 0, 0, .1); + } + + .swagger-ui .b--black-05 { + border-color: rgba(0, 0, 0, .05); + } + + .swagger-ui .b--black-025 { + border-color: rgba(0, 0, 0, .024); + } + + .swagger-ui .b--black-0125 { + border-color: rgba(0, 0, 0, .01); + } + + .swagger-ui .b--dark-red { + border-color: #bc2f36; + } + + .swagger-ui .b--red { + border-color: #c83932; + } + + .swagger-ui .b--light-red { + border-color: #ab3c2b; + } + + .swagger-ui .b--orange { + border-color: #cc6e33; + } + + .swagger-ui .b--purple { + border-color: #5e2ca5; + } + + .swagger-ui .b--light-purple { + border-color: #672caf; + } + + .swagger-ui .b--dark-pink { + border-color: #ab2b81; + } + + .swagger-ui .b--hot-pink { + border-color: #c03086; + } + + .swagger-ui .b--pink { + border-color: #8f2464; + } + + .swagger-ui .b--light-pink { + border-color: #721d4d; + } + + .swagger-ui .b--dark-green { + border-color: #1c6e50; + } + + .swagger-ui .b--green { + border-color: #279b70; + } + + .swagger-ui .b--light-green { + border-color: #228762; + } + + .swagger-ui .b--navy { + border-color: #0d1d35; + } + + .swagger-ui .b--dark-blue { + border-color: #20497e; + } + + .swagger-ui .b--blue { + border-color: #4380d0; + } + + .swagger-ui .b--light-blue { + border-color: #20517e; + } + + .swagger-ui .b--lightest-blue { + border-color: #143a52; + } + + .swagger-ui .b--washed-blue { + border-color: #0c312d; + } + + .swagger-ui .b--washed-green { + border-color: #0f3d2c; + } + + .swagger-ui .b--washed-red { + border-color: #411010; + } + + .swagger-ui .b--transparent { + border-color: transparent; + } + + .swagger-ui .b--gold, .swagger-ui .b--light-yellow, .swagger-ui .b--washed-yellow, .swagger-ui .b--yellow { + border-color: #664b00; + } + + .swagger-ui .shadow-1 { + box-shadow: rgba(0, 0, 0, .2) 0 0 4px 2px; + } + + .swagger-ui .shadow-2 { + box-shadow: rgba(0, 0, 0, .2) 0 0 8px 2px; + } + + .swagger-ui .shadow-3 { + box-shadow: rgba(0, 0, 0, .2) 2px 2px 4px 2px; + } + + .swagger-ui .shadow-4 { + box-shadow: rgba(0, 0, 0, .2) 2px 2px 8px 0; + } + + .swagger-ui .shadow-5 { + box-shadow: rgba(0, 0, 0, .2) 4px 4px 8px 0; + } + + @media screen and (min-width: 30em) { + .swagger-ui .shadow-1-ns { + box-shadow: rgba(0, 0, 0, .2) 0 0 4px 2px; + } + + .swagger-ui .shadow-2-ns { + box-shadow: rgba(0, 0, 0, .2) 0 0 8px 2px; + } + + .swagger-ui .shadow-3-ns { + box-shadow: rgba(0, 0, 0, .2) 2px 2px 4px 2px; + } + + .swagger-ui .shadow-4-ns { + box-shadow: rgba(0, 0, 0, .2) 2px 2px 8px 0; + } + + .swagger-ui .shadow-5-ns { + box-shadow: rgba(0, 0, 0, .2) 4px 4px 8px 0; + } + } + + @media screen and (max-width: 60em) and (min-width: 30em) { + .swagger-ui .shadow-1-m { + box-shadow: rgba(0, 0, 0, .2) 0 0 4px 2px; + } + + .swagger-ui .shadow-2-m { + box-shadow: rgba(0, 0, 0, .2) 0 0 8px 2px; + } + + .swagger-ui .shadow-3-m { + box-shadow: rgba(0, 0, 0, .2) 2px 2px 4px 2px; + } + + .swagger-ui .shadow-4-m { + box-shadow: rgba(0, 0, 0, .2) 2px 2px 8px 0; + } + + .swagger-ui .shadow-5-m { + box-shadow: rgba(0, 0, 0, .2) 4px 4px 8px 0; + } + } + + @media screen and (min-width: 60em) { + .swagger-ui .shadow-1-l { + box-shadow: rgba(0, 0, 0, .2) 0 0 4px 2px; + } + + .swagger-ui .shadow-2-l { + box-shadow: rgba(0, 0, 0, .2) 0 0 8px 2px; + } + + .swagger-ui .shadow-3-l { + box-shadow: rgba(0, 0, 0, .2) 2px 2px 4px 2px; + } + + .swagger-ui .shadow-4-l { + box-shadow: rgba(0, 0, 0, .2) 2px 2px 8px 0; + } + + .swagger-ui .shadow-5-l { + box-shadow: rgba(0, 0, 0, .2) 4px 4px 8px 0; + } + } + + .swagger-ui .black-05 { + color: rgba(191, 191, 191, .05); + } + + .swagger-ui .bg-black-05 { + background-color: rgba(0, 0, 0, .05); + } + + .swagger-ui .black-90, .swagger-ui .hover-black-90:focus, .swagger-ui .hover-black-90:hover { + color: rgba(191, 191, 191, .9); + } + + .swagger-ui .black-80, .swagger-ui .hover-black-80:focus, .swagger-ui .hover-black-80:hover { + color: rgba(191, 191, 191, .8); + } + + .swagger-ui .black-70, .swagger-ui .hover-black-70:focus, .swagger-ui .hover-black-70:hover { + color: rgba(191, 191, 191, .7); + } + + .swagger-ui .black-60, .swagger-ui .hover-black-60:focus, .swagger-ui .hover-black-60:hover { + color: rgba(191, 191, 191, .6); + } + + .swagger-ui .black-50, .swagger-ui .hover-black-50:focus, .swagger-ui .hover-black-50:hover { + color: rgba(191, 191, 191, .5); + } + + .swagger-ui .black-40, .swagger-ui .hover-black-40:focus, .swagger-ui .hover-black-40:hover { + color: rgba(191, 191, 191, .4); + } + + .swagger-ui .black-30, .swagger-ui .hover-black-30:focus, .swagger-ui .hover-black-30:hover { + color: rgba(191, 191, 191, .3); + } + + .swagger-ui .black-20, .swagger-ui .hover-black-20:focus, .swagger-ui .hover-black-20:hover { + color: rgba(191, 191, 191, .2); + } + + .swagger-ui .black-10, .swagger-ui .hover-black-10:focus, .swagger-ui .hover-black-10:hover { + color: rgba(191, 191, 191, .1); + } + + .swagger-ui .hover-white-90:focus, .swagger-ui .hover-white-90:hover, .swagger-ui .white-90 { + color: rgba(255, 255, 255, .9); + } + + .swagger-ui .hover-white-80:focus, .swagger-ui .hover-white-80:hover, .swagger-ui .white-80 { + color: rgba(255, 255, 255, .8); + } + + .swagger-ui .hover-white-70:focus, .swagger-ui .hover-white-70:hover, .swagger-ui .white-70 { + color: rgba(255, 255, 255, .7); + } + + .swagger-ui .hover-white-60:focus, .swagger-ui .hover-white-60:hover, .swagger-ui .white-60 { + color: rgba(255, 255, 255, .6); + } + + .swagger-ui .hover-white-50:focus, .swagger-ui .hover-white-50:hover, .swagger-ui .white-50 { + color: rgba(255, 255, 255, .5); + } + + .swagger-ui .hover-white-40:focus, .swagger-ui .hover-white-40:hover, .swagger-ui .white-40 { + color: rgba(255, 255, 255, .4); + } + + .swagger-ui .hover-white-30:focus, .swagger-ui .hover-white-30:hover, .swagger-ui .white-30 { + color: rgba(255, 255, 255, .3); + } + + .swagger-ui .hover-white-20:focus, .swagger-ui .hover-white-20:hover, .swagger-ui .white-20 { + color: rgba(255, 255, 255, .2); + } + + .swagger-ui .hover-white-10:focus, .swagger-ui .hover-white-10:hover, .swagger-ui .white-10 { + color: rgba(255, 255, 255, .1); + } + + .swagger-ui .hover-moon-gray:focus, .swagger-ui .hover-moon-gray:hover, .swagger-ui .moon-gray { + color: #ccc; + } + + .swagger-ui .hover-light-gray:focus, .swagger-ui .hover-light-gray:hover, .swagger-ui .light-gray { + color: #ededed; + } + + .swagger-ui .hover-near-white:focus, .swagger-ui .hover-near-white:hover, .swagger-ui .near-white { + color: #f5f5f5; + } + + .swagger-ui .dark-red, .swagger-ui .hover-dark-red:focus, .swagger-ui .hover-dark-red:hover { + color: #e6999d; + } + + .swagger-ui .hover-red:focus, .swagger-ui .hover-red:hover, .swagger-ui .red { + color: #e69d99; + } + + .swagger-ui .hover-light-red:focus, .swagger-ui .hover-light-red:hover, .swagger-ui .light-red { + color: #e6a399; + } + + .swagger-ui .hover-orange:focus, .swagger-ui .hover-orange:hover, .swagger-ui .orange { + color: #e6b699; + } + + .swagger-ui .gold, .swagger-ui .hover-gold:focus, .swagger-ui .hover-gold:hover { + color: #e6d099; + } + + .swagger-ui .hover-yellow:focus, .swagger-ui .hover-yellow:hover, .swagger-ui .yellow { + color: #e6da99; + } + + .swagger-ui .hover-light-yellow:focus, .swagger-ui .hover-light-yellow:hover, .swagger-ui .light-yellow { + color: #ede6b6; + } + + .swagger-ui .hover-purple:focus, .swagger-ui .hover-purple:hover, .swagger-ui .purple { + color: #b99ae4; + } + + .swagger-ui .hover-light-purple:focus, .swagger-ui .hover-light-purple:hover, .swagger-ui .light-purple { + color: #bb99e6; + } + + .swagger-ui .dark-pink, .swagger-ui .hover-dark-pink:focus, .swagger-ui .hover-dark-pink:hover { + color: #e699cc; + } + + .swagger-ui .hot-pink, .swagger-ui .hover-hot-pink:focus, .swagger-ui .hover-hot-pink:hover, .swagger-ui .hover-pink:focus, .swagger-ui .hover-pink:hover, .swagger-ui .pink { + color: #e699c7; + } + + .swagger-ui .hover-light-pink:focus, .swagger-ui .hover-light-pink:hover, .swagger-ui .light-pink { + color: #edb6d5; + } + + .swagger-ui .dark-green, .swagger-ui .green, .swagger-ui .hover-dark-green:focus, .swagger-ui .hover-dark-green:hover, .swagger-ui .hover-green:focus, .swagger-ui .hover-green:hover { + color: #99e6c9; + } + + .swagger-ui .hover-light-green:focus, .swagger-ui .hover-light-green:hover, .swagger-ui .light-green { + color: #a1e8ce; + } + + .swagger-ui .hover-navy:focus, .swagger-ui .hover-navy:hover, .swagger-ui .navy { + color: #99b8e6; + } + + .swagger-ui .blue, .swagger-ui .dark-blue, .swagger-ui .hover-blue:focus, .swagger-ui .hover-blue:hover, .swagger-ui .hover-dark-blue:focus, .swagger-ui .hover-dark-blue:hover { + color: #99bae6; + } + + .swagger-ui .hover-light-blue:focus, .swagger-ui .hover-light-blue:hover, .swagger-ui .light-blue { + color: #a9cbea; + } + + .swagger-ui .hover-lightest-blue:focus, .swagger-ui .hover-lightest-blue:hover, .swagger-ui .lightest-blue { + color: #d6e9f5; + } + + .swagger-ui .hover-washed-blue:focus, .swagger-ui .hover-washed-blue:hover, .swagger-ui .washed-blue { + color: #f7fdfc; + } + + .swagger-ui .hover-washed-green:focus, .swagger-ui .hover-washed-green:hover, .swagger-ui .washed-green { + color: #ebfaf4; + } + + .swagger-ui .hover-washed-yellow:focus, .swagger-ui .hover-washed-yellow:hover, .swagger-ui .washed-yellow { + color: #fbf9ef; + } + + .swagger-ui .hover-washed-red:focus, .swagger-ui .hover-washed-red:hover, .swagger-ui .washed-red { + color: #f9e7e7; + } + + .swagger-ui .color-inherit, .swagger-ui .hover-inherit:focus, .swagger-ui .hover-inherit:hover { + color: inherit; + } + + .swagger-ui .bg-black-90, .swagger-ui .hover-bg-black-90:focus, .swagger-ui .hover-bg-black-90:hover { + background-color: rgba(0, 0, 0, .9); + } + + .swagger-ui .bg-black-80, .swagger-ui .hover-bg-black-80:focus, .swagger-ui .hover-bg-black-80:hover { + background-color: rgba(0, 0, 0, .8); + } + + .swagger-ui .bg-black-70, .swagger-ui .hover-bg-black-70:focus, .swagger-ui .hover-bg-black-70:hover { + background-color: rgba(0, 0, 0, .7); + } + + .swagger-ui .bg-black-60, .swagger-ui .hover-bg-black-60:focus, .swagger-ui .hover-bg-black-60:hover { + background-color: rgba(0, 0, 0, .6); + } + + .swagger-ui .bg-black-50, .swagger-ui .hover-bg-black-50:focus, .swagger-ui .hover-bg-black-50:hover { + background-color: rgba(0, 0, 0, .5); + } + + .swagger-ui .bg-black-40, .swagger-ui .hover-bg-black-40:focus, .swagger-ui .hover-bg-black-40:hover { + background-color: rgba(0, 0, 0, .4); + } + + .swagger-ui .bg-black-30, .swagger-ui .hover-bg-black-30:focus, .swagger-ui .hover-bg-black-30:hover { + background-color: rgba(0, 0, 0, .3); + } + + .swagger-ui .bg-black-20, .swagger-ui .hover-bg-black-20:focus, .swagger-ui .hover-bg-black-20:hover { + background-color: rgba(0, 0, 0, .2); + } + + .swagger-ui .bg-white-90, .swagger-ui .hover-bg-white-90:focus, .swagger-ui .hover-bg-white-90:hover { + background-color: rgba(28, 28, 33, .9); + } + + .swagger-ui .bg-white-80, .swagger-ui .hover-bg-white-80:focus, .swagger-ui .hover-bg-white-80:hover { + background-color: rgba(28, 28, 33, .8); + } + + .swagger-ui .bg-white-70, .swagger-ui .hover-bg-white-70:focus, .swagger-ui .hover-bg-white-70:hover { + background-color: rgba(28, 28, 33, .7); + } + + .swagger-ui .bg-white-60, .swagger-ui .hover-bg-white-60:focus, .swagger-ui .hover-bg-white-60:hover { + background-color: rgba(28, 28, 33, .6); + } + + .swagger-ui .bg-white-50, .swagger-ui .hover-bg-white-50:focus, .swagger-ui .hover-bg-white-50:hover { + background-color: rgba(28, 28, 33, .5); + } + + .swagger-ui .bg-white-40, .swagger-ui .hover-bg-white-40:focus, .swagger-ui .hover-bg-white-40:hover { + background-color: rgba(28, 28, 33, .4); + } + + .swagger-ui .bg-white-30, .swagger-ui .hover-bg-white-30:focus, .swagger-ui .hover-bg-white-30:hover { + background-color: rgba(28, 28, 33, .3); + } + + .swagger-ui .bg-white-20, .swagger-ui .hover-bg-white-20:focus, .swagger-ui .hover-bg-white-20:hover { + background-color: rgba(28, 28, 33, .2); + } + + .swagger-ui .bg-black, .swagger-ui .hover-bg-black:focus, .swagger-ui .hover-bg-black:hover { + background-color: #000; + } + + .swagger-ui .bg-near-black, .swagger-ui .hover-bg-near-black:focus, .swagger-ui .hover-bg-near-black:hover { + background-color: #121212; + } + + .swagger-ui .bg-dark-gray, .swagger-ui .hover-bg-dark-gray:focus, .swagger-ui .hover-bg-dark-gray:hover { + background-color: #333; + } + + .swagger-ui .bg-mid-gray, .swagger-ui .hover-bg-mid-gray:focus, .swagger-ui .hover-bg-mid-gray:hover { + background-color: #545454; + } + + .swagger-ui .bg-gray, .swagger-ui .hover-bg-gray:focus, .swagger-ui .hover-bg-gray:hover { + background-color: #787878; + } + + .swagger-ui .bg-silver, .swagger-ui .hover-bg-silver:focus, .swagger-ui .hover-bg-silver:hover { + background-color: #999; + } + + .swagger-ui .bg-white, .swagger-ui .hover-bg-white:focus, .swagger-ui .hover-bg-white:hover { + background-color: #1c1c21; + } + + .swagger-ui .bg-transparent, .swagger-ui .hover-bg-transparent:focus, .swagger-ui .hover-bg-transparent:hover { + background-color: transparent; + } + + .swagger-ui .bg-dark-red, .swagger-ui .hover-bg-dark-red:focus, .swagger-ui .hover-bg-dark-red:hover { + background-color: #bc2f36; + } + + .swagger-ui .bg-red, .swagger-ui .hover-bg-red:focus, .swagger-ui .hover-bg-red:hover { + background-color: #c83932; + } + + .swagger-ui .bg-light-red, .swagger-ui .hover-bg-light-red:focus, .swagger-ui .hover-bg-light-red:hover { + background-color: #ab3c2b; + } + + .swagger-ui .bg-orange, .swagger-ui .hover-bg-orange:focus, .swagger-ui .hover-bg-orange:hover { + background-color: #cc6e33; + } + + .swagger-ui .bg-gold, .swagger-ui .bg-light-yellow, .swagger-ui .bg-washed-yellow, .swagger-ui .bg-yellow, .swagger-ui .hover-bg-gold:focus, .swagger-ui .hover-bg-gold:hover, .swagger-ui .hover-bg-light-yellow:focus, .swagger-ui .hover-bg-light-yellow:hover, .swagger-ui .hover-bg-washed-yellow:focus, .swagger-ui .hover-bg-washed-yellow:hover, .swagger-ui .hover-bg-yellow:focus, .swagger-ui .hover-bg-yellow:hover { + background-color: #664b00; + } + + .swagger-ui .bg-purple, .swagger-ui .hover-bg-purple:focus, .swagger-ui .hover-bg-purple:hover { + background-color: #5e2ca5; + } + + .swagger-ui .bg-light-purple, .swagger-ui .hover-bg-light-purple:focus, .swagger-ui .hover-bg-light-purple:hover { + background-color: #672caf; + } + + .swagger-ui .bg-dark-pink, .swagger-ui .hover-bg-dark-pink:focus, .swagger-ui .hover-bg-dark-pink:hover { + background-color: #ab2b81; + } + + .swagger-ui .bg-hot-pink, .swagger-ui .hover-bg-hot-pink:focus, .swagger-ui .hover-bg-hot-pink:hover { + background-color: #c03086; + } + + .swagger-ui .bg-pink, .swagger-ui .hover-bg-pink:focus, .swagger-ui .hover-bg-pink:hover { + background-color: #8f2464; + } + + .swagger-ui .bg-light-pink, .swagger-ui .hover-bg-light-pink:focus, .swagger-ui .hover-bg-light-pink:hover { + background-color: #721d4d; + } + + .swagger-ui .bg-dark-green, .swagger-ui .hover-bg-dark-green:focus, .swagger-ui .hover-bg-dark-green:hover { + background-color: #1c6e50; + } + + .swagger-ui .bg-green, .swagger-ui .hover-bg-green:focus, .swagger-ui .hover-bg-green:hover { + background-color: #279b70; + } + + .swagger-ui .bg-light-green, .swagger-ui .hover-bg-light-green:focus, .swagger-ui .hover-bg-light-green:hover { + background-color: #228762; + } + + .swagger-ui .bg-navy, .swagger-ui .hover-bg-navy:focus, .swagger-ui .hover-bg-navy:hover { + background-color: #0d1d35; + } + + .swagger-ui .bg-dark-blue, .swagger-ui .hover-bg-dark-blue:focus, .swagger-ui .hover-bg-dark-blue:hover { + background-color: #20497e; + } + + .swagger-ui .bg-blue, .swagger-ui .hover-bg-blue:focus, .swagger-ui .hover-bg-blue:hover { + background-color: #4380d0; + } + + .swagger-ui .bg-light-blue, .swagger-ui .hover-bg-light-blue:focus, .swagger-ui .hover-bg-light-blue:hover { + background-color: #20517e; + } + + .swagger-ui .bg-lightest-blue, .swagger-ui .hover-bg-lightest-blue:focus, .swagger-ui .hover-bg-lightest-blue:hover { + background-color: #143a52; + } + + .swagger-ui .bg-washed-blue, .swagger-ui .hover-bg-washed-blue:focus, .swagger-ui .hover-bg-washed-blue:hover { + background-color: #0c312d; + } + + .swagger-ui .bg-washed-green, .swagger-ui .hover-bg-washed-green:focus, .swagger-ui .hover-bg-washed-green:hover { + background-color: #0f3d2c; + } + + .swagger-ui .bg-washed-red, .swagger-ui .hover-bg-washed-red:focus, .swagger-ui .hover-bg-washed-red:hover { + background-color: #411010; + } + + .swagger-ui .bg-inherit, .swagger-ui .hover-bg-inherit:focus, .swagger-ui .hover-bg-inherit:hover { + background-color: inherit; + } + + .swagger-ui .shadow-hover { + transition: all .5s cubic-bezier(.165, .84, .44, 1) 0s; + } + + .swagger-ui .shadow-hover::after { + border-radius: inherit; + box-shadow: rgba(0, 0, 0, .2) 0 0 16px 2px; + content: ""; + height: 100%; + left: 0; + opacity: 0; + position: absolute; + top: 0; + transition: opacity .5s cubic-bezier(.165, .84, .44, 1) 0s; + width: 100%; + z-index: -1; + } + + .swagger-ui .bg-animate, .swagger-ui .bg-animate:focus, .swagger-ui .bg-animate:hover { + transition: background-color .15s ease-in-out 0s; + } + + .swagger-ui .nested-links a { + color: #99bae6; + transition: color .15s ease-in 0s; + } + + .swagger-ui .nested-links a:focus, .swagger-ui .nested-links a:hover { + color: #a9cbea; + transition: color .15s ease-in 0s; + } + + .swagger-ui .opblock-tag { + border-bottom: 1px solid rgba(58, 64, 80, .3); + color: #b5bac9; + transition: all .2s ease 0s; + } + + .swagger-ui .opblock-tag svg, .swagger-ui section.models h4 svg { + transition: all .4s ease 0s; + } + + .swagger-ui .opblock { + border: 1px solid #000; + border-radius: 4px; + box-shadow: rgba(0, 0, 0, .19) 0 0 3px; + margin: 0 0 15px; + } + + .swagger-ui .opblock .tab-header .tab-item.active h4 span::after { + background: gray; + } + + .swagger-ui .opblock.is-open .opblock-summary { + border-bottom: 1px solid #000; + } + + .swagger-ui .opblock .opblock-section-header { + background: rgba(28, 28, 33, .8); + box-shadow: rgba(0, 0, 0, .1) 0 1px 2px; + } + + .swagger-ui .opblock .opblock-section-header > label > span { + padding: 0 10px 0 0; + } + + .swagger-ui .opblock .opblock-summary-method { + background: #000; + color: #fff; + text-shadow: rgba(0, 0, 0, .1) 0 1px 0; + } + + .swagger-ui .opblock.opblock-post { + background: rgba(72, 203, 144, .1); + border-color: #48cb90; + } + + .swagger-ui .opblock.opblock-post .opblock-summary-method, .swagger-ui .opblock.opblock-post .tab-header .tab-item.active h4 span::after { + background: #48cb90; + } + + .swagger-ui .opblock.opblock-post .opblock-summary { + border-color: #48cb90; + } + + .swagger-ui .opblock.opblock-put { + background: rgba(213, 157, 88, .1); + border-color: #d59d58; + } + + .swagger-ui .opblock.opblock-put .opblock-summary-method, .swagger-ui .opblock.opblock-put .tab-header .tab-item.active h4 span::after { + background: #d59d58; + } + + .swagger-ui .opblock.opblock-put .opblock-summary { + border-color: #d59d58; + } + + .swagger-ui .opblock.opblock-delete { + background: rgba(200, 50, 50, .1); + border-color: #c83232; + } + + .swagger-ui .opblock.opblock-delete .opblock-summary-method, .swagger-ui .opblock.opblock-delete .tab-header .tab-item.active h4 span::after { + background: #c83232; + } + + .swagger-ui .opblock.opblock-delete .opblock-summary { + border-color: #c83232; + } + + .swagger-ui .opblock.opblock-get { + background: rgba(42, 105, 167, .1); + border-color: #2a69a7; + } + + .swagger-ui .opblock.opblock-get .opblock-summary-method, .swagger-ui .opblock.opblock-get .tab-header .tab-item.active h4 span::after { + background: #2a69a7; + } + + .swagger-ui .opblock.opblock-get .opblock-summary { + border-color: #2a69a7; + } + + .swagger-ui .opblock.opblock-patch { + background: rgba(92, 214, 188, .1); + border-color: #5cd6bc; + } + + .swagger-ui .opblock.opblock-patch .opblock-summary-method, .swagger-ui .opblock.opblock-patch .tab-header .tab-item.active h4 span::after { + background: #5cd6bc; + } + + .swagger-ui .opblock.opblock-patch .opblock-summary { + border-color: #5cd6bc; + } + + .swagger-ui .opblock.opblock-head { + background: rgba(140, 63, 207, .1); + border-color: #8c3fcf; + } + + .swagger-ui .opblock.opblock-head .opblock-summary-method, .swagger-ui .opblock.opblock-head .tab-header .tab-item.active h4 span::after { + background: #8c3fcf; + } + + .swagger-ui .opblock.opblock-head .opblock-summary { + border-color: #8c3fcf; + } + + .swagger-ui .opblock.opblock-options { + background: rgba(36, 89, 143, .1); + border-color: #24598f; + } + + .swagger-ui .opblock.opblock-options .opblock-summary-method, .swagger-ui .opblock.opblock-options .tab-header .tab-item.active h4 span::after { + background: #24598f; + } + + .swagger-ui .opblock.opblock-options .opblock-summary { + border-color: #24598f; + } + + .swagger-ui .opblock.opblock-deprecated { + background: rgba(46, 46, 46, .1); + border-color: #2e2e2e; + opacity: .6; + } + + .swagger-ui .opblock.opblock-deprecated .opblock-summary-method, .swagger-ui .opblock.opblock-deprecated .tab-header .tab-item.active h4 span::after { + background: #2e2e2e; + } + + .swagger-ui .opblock.opblock-deprecated .opblock-summary { + border-color: #2e2e2e; + } + + .swagger-ui .filter .operation-filter-input { + border: 2px solid #2b3446; + } + + .swagger-ui .tab li:first-of-type::after { + background: rgba(0, 0, 0, .2); + } + + .swagger-ui .download-contents { + background: #7c8192; + color: #fff; + } + + .swagger-ui .scheme-container { + background: #1c1c21; + box-shadow: rgba(0, 0, 0, .15) 0 1px 2px 0; + } + + .swagger-ui .loading-container .loading::before { + animation: 1s linear 0s infinite normal none running rotation, .5s ease 0s 1 normal none running opacity; + border-color: rgba(0, 0, 0, .6) rgba(84, 84, 84, .1) rgba(84, 84, 84, .1); + } + + .swagger-ui .response-control-media-type--accept-controller select { + border-color: #196619; + } + + .swagger-ui .response-control-media-type__accept-message { + color: #99e699; + } + + .swagger-ui .version-pragma__message code { + background-color: #3b3b3b; + } + + .swagger-ui .btn { + background: 0 0; + border: 2px solid gray; + box-shadow: rgba(0, 0, 0, .1) 0 1px 2px; + color: #b5bac9; + } + + .swagger-ui .btn:hover { + box-shadow: rgba(0, 0, 0, .3) 0 0 5px; + } + + .swagger-ui .btn.authorize, .swagger-ui .btn.cancel { + background-color: transparent; + border-color: #a72a2a; + color: #e69999; + } + + .swagger-ui .btn.cancel:hover { + background-color: #a72a2a; + color: #fff; + } + + .swagger-ui .btn.authorize { + border-color: #48cb90; + color: #9ce3c3; + } + + .swagger-ui .btn.authorize svg { + fill: #9ce3c3; + } + + .btn.authorize.unlocked:hover { + background-color: #48cb90; + color: #fff; + } + + .btn.authorize.unlocked:hover svg { + fill: #fbfbfb; + } + + .swagger-ui .btn.execute { + background-color: #5892d5; + border-color: #5892d5; + color: #fff; + } + + .swagger-ui .copy-to-clipboard { + background: #7c8192; + } + + .swagger-ui .copy-to-clipboard button { + background: url("data:image/svg+xml;charset=utf-8,") 50% center no-repeat; + } + + .swagger-ui select { + background: url("data:image/svg+xml;charset=utf-8,") right 10px center/20px no-repeat #212121; + background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgaW5rc2NhcGU6dmVyc2lvbj0iMS4wICg0MDM1YTRmYjQ5LCAyMDIwLTA1LTAxKSIKICAgc29kaXBvZGk6ZG9jbmFtZT0iZG93bmxvYWQuc3ZnIgogICBpZD0ic3ZnNCIKICAgdmVyc2lvbj0iMS4xIgogICB2aWV3Qm94PSIwIDAgMjAgMjAiPgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTEwIj4KICAgIDxyZGY6UkRGPgogICAgICA8Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+CiAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+CiAgICAgICAgPGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPgogICAgICA8L2NjOldvcms+CiAgICA8L3JkZjpSREY+CiAgPC9tZXRhZGF0YT4KICA8ZGVmcwogICAgIGlkPSJkZWZzOCIgLz4KICA8c29kaXBvZGk6bmFtZWR2aWV3CiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ic3ZnNCIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIgogICAgIGlua3NjYXBlOndpbmRvdy15PSItOSIKICAgICBpbmtzY2FwZTp3aW5kb3cteD0iLTkiCiAgICAgaW5rc2NhcGU6Y3k9IjEwIgogICAgIGlua3NjYXBlOmN4PSIxMCIKICAgICBpbmtzY2FwZTp6b29tPSI0MS41IgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpZD0ibmFtZWR2aWV3NiIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSIxMDAxIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTkyMCIKICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIgogICAgIGd1aWRldG9sZXJhbmNlPSIxMCIKICAgICBncmlkdG9sZXJhbmNlPSIxMCIKICAgICBvYmplY3R0b2xlcmFuY2U9IjEwIgogICAgIGJvcmRlcm9wYWNpdHk9IjEiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIiAvPgogIDxwYXRoCiAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZiIKICAgICBpZD0icGF0aDIiCiAgICAgZD0iTTEzLjQxOCA3Ljg1OWEuNjk1LjY5NSAwIDAxLjk3OCAwIC42OC42OCAwIDAxMCAuOTY5bC0zLjkwOCAzLjgzYS42OTcuNjk3IDAgMDEtLjk3OSAwbC0zLjkwOC0zLjgzYS42OC42OCAwIDAxMC0uOTY5LjY5NS42OTUgMCAwMS45NzggMEwxMCAxMWwzLjQxOC0zLjE0MXoiIC8+Cjwvc3ZnPgo=) right 10px center/20px no-repeat #1c1c21; + border: 2px solid #41444e; + } + + .swagger-ui select[multiple] { + background: #212121; + } + + .swagger-ui button.invalid, .swagger-ui input[type=email].invalid, .swagger-ui input[type=file].invalid, .swagger-ui input[type=password].invalid, .swagger-ui input[type=search].invalid, .swagger-ui input[type=text].invalid, .swagger-ui select.invalid, .swagger-ui textarea.invalid { + background: #390e0e; + border-color: #c83232; + } + + .swagger-ui input[type=email], .swagger-ui input[type=file], .swagger-ui input[type=password], .swagger-ui input[type=search], .swagger-ui input[type=text], .swagger-ui textarea { + background: #1c1c21; + border: 1px solid #404040; + } + + .swagger-ui textarea { + background: rgba(28, 28, 33, .8); + color: #b5bac9; + } + + .swagger-ui input[disabled], .swagger-ui select[disabled] { + background-color: #1f1f1f; + color: #bfbfbf; + } + + .swagger-ui textarea[disabled] { + background-color: #41444e; + color: #fff; + } + + .swagger-ui select[disabled] { + border-color: #878787; + } + + .swagger-ui textarea:focus { + border: 2px solid #2a69a7; + } + + .swagger-ui .checkbox input[type=checkbox] + label > .item { + background: #303030; + box-shadow: #303030 0 0 0 2px; + } + + .swagger-ui .checkbox input[type=checkbox]:checked + label > .item { + background: url("data:image/svg+xml;charset=utf-8,") 50% center no-repeat #303030; + } + + .swagger-ui .dialog-ux .backdrop-ux { + background: rgba(0, 0, 0, .8); + } + + .swagger-ui .dialog-ux .modal-ux { + background: #1c1c21; + border: 1px solid #2e2e2e; + box-shadow: rgba(0, 0, 0, .2) 0 10px 30px 0; + } + + .swagger-ui .dialog-ux .modal-ux-header .close-modal { + background: 0 0; + } + + .swagger-ui .model .deprecated span, .swagger-ui .model .deprecated td { + color: #bfbfbf !important; + } + + .swagger-ui .model-toggle::after { + background: url("data:image/svg+xml;charset=utf-8,") 50% center/100% no-repeat; + } + + .swagger-ui .model-hint { + background: rgba(0, 0, 0, .7); + color: #ebebeb; + } + + .swagger-ui section.models { + border: 1px solid rgba(58, 64, 80, .3); + } + + .swagger-ui section.models.is-open h4 { + border-bottom: 1px solid rgba(58, 64, 80, .3); + } + + .swagger-ui section.models .model-container { + background: rgba(0, 0, 0, .05); + } + + .swagger-ui section.models .model-container:hover { + background: rgba(0, 0, 0, .07); + } + + .swagger-ui .model-box { + background: rgba(0, 0, 0, .1); + } + + .swagger-ui .prop-type { + color: #aaaad4; + } + + .swagger-ui table thead tr td, .swagger-ui table thead tr th { + border-bottom: 1px solid rgba(58, 64, 80, .2); + color: #b5bac9; + } + + .swagger-ui .parameter__name.required::after { + color: rgba(230, 153, 153, .6); + } + + .swagger-ui .topbar .download-url-wrapper .select-label { + color: #f0f0f0; + } + + .swagger-ui .topbar .download-url-wrapper .download-url-button { + background: #63a040; + color: #fff; + } + + .swagger-ui .info .title small { + background: #7c8492; + } + + .swagger-ui .info .title small.version-stamp { + background-color: #7a9b27; + } + + .swagger-ui .auth-container .errors { + background-color: #350d0d; + color: #b5bac9; + } + + .swagger-ui .errors-wrapper { + background: rgba(200, 50, 50, .1); + border: 2px solid #c83232; + } + + .swagger-ui .markdown code, .swagger-ui .renderedmarkdown code { + background: rgba(0, 0, 0, .05); + color: #c299e6; + } + + .swagger-ui .model-toggle:after { + background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgaW5rc2NhcGU6dmVyc2lvbj0iMS4wICg0MDM1YTRmYjQ5LCAyMDIwLTA1LTAxKSIKICAgc29kaXBvZGk6ZG9jbmFtZT0iZG93bmxvYWQyLnN2ZyIKICAgaWQ9InN2ZzQiCiAgIHZlcnNpb249IjEuMSIKICAgaGVpZ2h0PSIyNCIKICAgd2lkdGg9IjI0Ij4KICA8bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGExMCI+CiAgICA8cmRmOlJERj4KICAgICAgPGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPgogICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PgogICAgICAgIDxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz4KICAgICAgPC9jYzpXb3JrPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPGRlZnMKICAgICBpZD0iZGVmczgiIC8+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2ZzQiCiAgICAgaW5rc2NhcGU6d2luZG93LW1heGltaXplZD0iMSIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iLTkiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9Ii05IgogICAgIGlua3NjYXBlOmN5PSIxMiIKICAgICBpbmtzY2FwZTpjeD0iMTIiCiAgICAgaW5rc2NhcGU6em9vbT0iMzQuNTgzMzMzIgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpZD0ibmFtZWR2aWV3NiIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSIxMDAxIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTkyMCIKICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIgogICAgIGd1aWRldG9sZXJhbmNlPSIxMCIKICAgICBncmlkdG9sZXJhbmNlPSIxMCIKICAgICBvYmplY3R0b2xlcmFuY2U9IjEwIgogICAgIGJvcmRlcm9wYWNpdHk9IjEiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIiAvPgogIDxwYXRoCiAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZiIKICAgICBpZD0icGF0aDIiCiAgICAgZD0iTTEwIDZMOC41OSA3LjQxIDEzLjE3IDEybC00LjU4IDQuNTlMMTAgMThsNi02eiIgLz4KPC9zdmc+Cg==) 50% no-repeat; + } + + /* arrows for each operation and request are now white */ + + .arrow, #large-arrow-up { + fill: #fff; + } + + #unlocked { + fill: #fff; + } + + .swagger-ui .black, .swagger-ui .checkbox, .swagger-ui .dark-gray, .swagger-ui .download-url-wrapper .loading, .swagger-ui .errors-wrapper .errors small, .swagger-ui .fallback, .swagger-ui .filter .loading, .swagger-ui .gray, .swagger-ui .hover-black:focus, .swagger-ui .hover-black:hover, .swagger-ui .hover-dark-gray:focus, .swagger-ui .hover-dark-gray:hover, .swagger-ui .hover-gray:focus, .swagger-ui .hover-gray:hover, .swagger-ui .hover-light-silver:focus, .swagger-ui .hover-light-silver:hover, .swagger-ui .hover-mid-gray:focus, .swagger-ui .hover-mid-gray:hover, .swagger-ui .hover-near-black:focus, .swagger-ui .hover-near-black:hover, .swagger-ui .hover-silver:focus, .swagger-ui .hover-silver:hover, .swagger-ui .light-silver, .swagger-ui .markdown pre, .swagger-ui .mid-gray, .swagger-ui .model .property, .swagger-ui .model .property.primitive, .swagger-ui .model-title, .swagger-ui .near-black, .swagger-ui .parameter__extension, .swagger-ui .parameter__in, .swagger-ui .prop-format, .swagger-ui .renderedmarkdown pre, .swagger-ui .response-col_links .response-undocumented, .swagger-ui .response-col_status .response-undocumented, .swagger-ui .silver, .swagger-ui section.models h4, .swagger-ui section.models h5, .swagger-ui span.token-not-formatted, .swagger-ui span.token-string, .swagger-ui table.headers .header-example, .swagger-ui table.model tr.description, .swagger-ui table.model tr.extension { + color: #bfbfbf; + } + + .swagger-ui .hover-white:focus, .swagger-ui .hover-white:hover, .swagger-ui .info .title small pre, .swagger-ui .topbar a, .swagger-ui .white { + color: #fff; + } + + .swagger-ui .bg-black-10, .swagger-ui .hover-bg-black-10:focus, .swagger-ui .hover-bg-black-10:hover, .swagger-ui .stripe-dark:nth-child(2n + 1) { + background-color: rgba(0, 0, 0, .1); + } + + .swagger-ui .bg-white-10, .swagger-ui .hover-bg-white-10:focus, .swagger-ui .hover-bg-white-10:hover, .swagger-ui .stripe-light:nth-child(2n + 1) { + background-color: rgba(28, 28, 33, .1); + } + + .swagger-ui .bg-light-silver, .swagger-ui .hover-bg-light-silver:focus, .swagger-ui .hover-bg-light-silver:hover, .swagger-ui .striped--light-silver:nth-child(2n + 1) { + background-color: #6e6e6e; + } + + .swagger-ui .bg-moon-gray, .swagger-ui .hover-bg-moon-gray:focus, .swagger-ui .hover-bg-moon-gray:hover, .swagger-ui .striped--moon-gray:nth-child(2n + 1) { + background-color: #4d4d4d; + } + + .swagger-ui .bg-light-gray, .swagger-ui .hover-bg-light-gray:focus, .swagger-ui .hover-bg-light-gray:hover, .swagger-ui .striped--light-gray:nth-child(2n + 1) { + background-color: #2b2b2b; + } + + .swagger-ui .bg-near-white, .swagger-ui .hover-bg-near-white:focus, .swagger-ui .hover-bg-near-white:hover, .swagger-ui .striped--near-white:nth-child(2n + 1) { + background-color: #242424; + } + + .swagger-ui .opblock-tag:hover, .swagger-ui section.models h4:hover { + background: rgba(0, 0, 0, .02); + } + + .swagger-ui .checkbox p, .swagger-ui .dialog-ux .modal-ux-content h4, .swagger-ui .dialog-ux .modal-ux-content p, .swagger-ui .dialog-ux .modal-ux-header h3, .swagger-ui .errors-wrapper .errors h4, .swagger-ui .errors-wrapper hgroup h4, .swagger-ui .info .base-url, .swagger-ui .info .title, .swagger-ui .info h1, .swagger-ui .info h2, .swagger-ui .info h3, .swagger-ui .info h4, .swagger-ui .info h5, .swagger-ui .info li, .swagger-ui .info p, .swagger-ui .info table, .swagger-ui .loading-container .loading::after, .swagger-ui .model, .swagger-ui .opblock .opblock-section-header h4, .swagger-ui .opblock .opblock-section-header > label, .swagger-ui .opblock .opblock-summary-description, .swagger-ui .opblock .opblock-summary-operation-id, .swagger-ui .opblock .opblock-summary-path, .swagger-ui .opblock .opblock-summary-path__deprecated, .swagger-ui .opblock-description-wrapper, .swagger-ui .opblock-description-wrapper h4, .swagger-ui .opblock-description-wrapper p, .swagger-ui .opblock-external-docs-wrapper, .swagger-ui .opblock-external-docs-wrapper h4, .swagger-ui .opblock-external-docs-wrapper p, .swagger-ui .opblock-tag small, .swagger-ui .opblock-title_normal, .swagger-ui .opblock-title_normal h4, .swagger-ui .opblock-title_normal p, .swagger-ui .parameter__name, .swagger-ui .parameter__type, .swagger-ui .response-col_links, .swagger-ui .response-col_status, .swagger-ui .responses-inner h4, .swagger-ui .responses-inner h5, .swagger-ui .scheme-container .schemes > label, .swagger-ui .scopes h2, .swagger-ui .servers > label, .swagger-ui .tab li, .swagger-ui label, .swagger-ui select, .swagger-ui table.headers td { + color: #b5bac9; + } + + .swagger-ui .download-url-wrapper .failed, .swagger-ui .filter .failed, .swagger-ui .model-deprecated-warning, .swagger-ui .parameter__deprecated, .swagger-ui .parameter__name.required span, .swagger-ui table.model tr.property-row .star { + color: #e69999; + } + + .swagger-ui .opblock-body pre.microlight, .swagger-ui textarea.curl { + background: #41444e; + border-radius: 4px; + color: #fff; + } + + .swagger-ui .expand-methods svg, .swagger-ui .expand-methods:hover svg { + fill: #bfbfbf; + } + + .swagger-ui .auth-container, .swagger-ui .dialog-ux .modal-ux-header { + border-bottom: 1px solid #2e2e2e; + } + + .swagger-ui .topbar .download-url-wrapper .select-label select, .swagger-ui .topbar .download-url-wrapper input[type=text] { + border: 2px solid #63a040; + } + + .swagger-ui .info a, .swagger-ui .info a:hover, .swagger-ui .scopes h2 a { + color: #99bde6; + } +} diff --git a/web-src/assets/base.css b/web-src/assets/base.css deleted file mode 100644 index 8816868..0000000 --- a/web-src/assets/base.css +++ /dev/null @@ -1,86 +0,0 @@ -/* color palette from */ -:root { - --vt-c-white: #ffffff; - --vt-c-white-soft: #f8f8f8; - --vt-c-white-mute: #f2f2f2; - - --vt-c-black: #181818; - --vt-c-black-soft: #222222; - --vt-c-black-mute: #282828; - - --vt-c-indigo: #2c3e50; - - --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); - --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); - --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); - --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); - - --vt-c-text-light-1: var(--vt-c-indigo); - --vt-c-text-light-2: rgba(60, 60, 60, 0.66); - --vt-c-text-dark-1: var(--vt-c-white); - --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); -} - -/* semantic color variables for this project */ -:root { - --color-background: var(--vt-c-white); - --color-background-soft: var(--vt-c-white-soft); - --color-background-mute: var(--vt-c-white-mute); - - --color-border: var(--vt-c-divider-light-2); - --color-border-hover: var(--vt-c-divider-light-1); - - --color-heading: var(--vt-c-text-light-1); - --color-text: var(--vt-c-text-light-1); - - --section-gap: 160px; -} - -@media (prefers-color-scheme: dark) { - :root { - --color-background: var(--vt-c-black); - --color-background-soft: var(--vt-c-black-soft); - --color-background-mute: var(--vt-c-black-mute); - - --color-border: var(--vt-c-divider-dark-2); - --color-border-hover: var(--vt-c-divider-dark-1); - - --color-heading: var(--vt-c-text-dark-1); - --color-text: var(--vt-c-text-dark-2); - } -} - -*, -*::before, -*::after { - box-sizing: border-box; - margin: 0; - font-weight: normal; -} - -body { - min-height: 100vh; - color: var(--color-text); - background: var(--color-background); - transition: - color 0.5s, - background-color 0.5s; - line-height: 1.6; - font-family: - Inter, - -apple-system, - BlinkMacSystemFont, - 'Segoe UI', - Roboto, - Oxygen, - Ubuntu, - Cantarell, - 'Fira Sans', - 'Droid Sans', - 'Helvetica Neue', - sans-serif; - font-size: 15px; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} diff --git a/web-src/assets/index.scss b/web-src/assets/index.scss new file mode 100644 index 0000000..f2f2e51 --- /dev/null +++ b/web-src/assets/index.scss @@ -0,0 +1,141 @@ +@use "var"; + +:where(*) { + padding: 0; + margin: 0; + border: 0; + transition: background-color 0.3s ease; +} + +html { + color: #3c3c3c; + font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif; +} + +html.dark { + color: #d5d5d5; +} + +.swagger-ui .info { + margin: 0 !important; +} + + +::-webkit-scrollbar { + width: 14px; + height: 14px; +} + +::-webkit-scrollbar-button { + background-color: #8f8f8f !important; +} + +::-webkit-scrollbar-track { + background-color: #f5f5f5 !important; +} + +::-webkit-scrollbar-track-piece { + background-color: #e0e0e0 !important; +} + +::-webkit-scrollbar-thumb { + height: 50px; + background-color: #bdbdbd !important; + border: 2px solid #e0e0e0 !important; +} + +::-webkit-scrollbar-button:vertical:start:decrement { + background: linear-gradient(130deg, #cccccc 40%, transparent 41%), + linear-gradient(230deg, #cccccc 40%, transparent 41%), + linear-gradient(0deg, #cccccc 40%, transparent 31%); + background-color: #cccccc; +} + +::-webkit-scrollbar-button:vertical:end:increment { + background: linear-gradient(310deg, #cccccc 40%, transparent 41%), + linear-gradient(50deg, #cccccc 40%, transparent 41%), + linear-gradient(180deg, #cccccc 40%, transparent 31%); + background-color: #cccccc; +} + +::-webkit-scrollbar-button:horizontal:end:increment { + background: linear-gradient(210deg, #9e9e9e 40%, transparent 41%), + linear-gradient(330deg, #9e9e9e 40%, transparent 41%), + linear-gradient(90deg, #9e9e9e 30%, transparent 31%); + background-color: #ffffff; +} + +::-webkit-scrollbar-button:horizontal:start:decrement { + background: linear-gradient(30deg, #9e9e9e 40%, transparent 41%), + linear-gradient(150deg, #9e9e9e 40%, transparent 41%), + linear-gradient(270deg, #9e9e9e 30%, transparent 31%); + background-color: #ffffff; +} + + +html.dark { + + :where(body) { + background: #202020; + } + + ::-webkit-scrollbar { + width: 14px; + height: 14px; + } + + ::-webkit-scrollbar-button { + background-color: #3e4346 !important; + } + + ::-webkit-scrollbar-track { + background-color: #646464 !important; + } + + ::-webkit-scrollbar-track-piece { + background-color: #3e4346 !important; + } + + ::-webkit-scrollbar-thumb { + height: 50px; + background-color: #242424 !important; + border: 2px solid #3e4346 !important; + } + + ::-webkit-scrollbar-button:vertical:start:decrement { + background: linear-gradient(130deg, #696969 40%, rgba(255, 0, 0, 0) 41%), + linear-gradient(230deg, #696969 40%, rgba(0, 0, 0, 0) 41%), + linear-gradient(0deg, #696969 40%, rgba(0, 0, 0, 0) 31%); + background-color: #b6b6b6; + } + + ::-webkit-scrollbar-button:vertical:end:increment { + background: linear-gradient(310deg, #696969 40%, rgba(0, 0, 0, 0) 41%), + linear-gradient(50deg, #696969 40%, rgba(0, 0, 0, 0) 41%), + linear-gradient(180deg, #696969 40%, rgba(0, 0, 0, 0) 31%); + background-color: #b6b6b6; + } + + ::-webkit-scrollbar-button:horizontal:end:increment { + background: linear-gradient(210deg, #696969 40%, rgba(0, 0, 0, 0) 41%), + linear-gradient(330deg, #696969 40%, rgba(0, 0, 0, 0) 41%), + linear-gradient(90deg, #696969 30%, rgba(0, 0, 0, 0) 31%); + background-color: #b6b6b6; + } + + ::-webkit-scrollbar-button:horizontal:start:decrement { + background: linear-gradient(30deg, #696969 40%, rgba(0, 0, 0, 0) 41%), + linear-gradient(150deg, #696969 40%, rgba(0, 0, 0, 0) 41%), + linear-gradient(270deg, #696969 30%, rgba(0, 0, 0, 0) 31%); + background-color: #b6b6b6; + } +} + + +.n-drawer-mask { + backdrop-filter: blur(2px); +} + +.n-message { + padding: 8px; +} diff --git a/web-src/assets/icon.svg b/web-src/assets/index.svg similarity index 100% rename from web-src/assets/icon.svg rename to web-src/assets/index.svg diff --git a/web-src/assets/main.css b/web-src/assets/main.css deleted file mode 100644 index 36fb845..0000000 --- a/web-src/assets/main.css +++ /dev/null @@ -1,35 +0,0 @@ -@import './base.css'; - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - font-weight: normal; -} - -a, -.green { - text-decoration: none; - color: hsla(160, 100%, 37%, 1); - transition: 0.4s; - padding: 3px; -} - -@media (hover: hover) { - a:hover { - background-color: hsla(160, 100%, 37%, 0.2); - } -} - -@media (min-width: 1024px) { - body { - display: flex; - place-items: center; - } - - #app { - display: grid; - grid-template-columns: 1fr 1fr; - padding: 0 2rem; - } -} diff --git a/web-src/assets/var.scss b/web-src/assets/var.scss new file mode 100644 index 0000000..331ffca --- /dev/null +++ b/web-src/assets/var.scss @@ -0,0 +1,16 @@ +*[n-c] { + align-items: center; +} + +*[c-n] { + justify-content: center; +} + +*[c-c] { + justify-content: center; + align-items: center; +} + +*[f] { + display: flex; +} diff --git a/web-src/components/HelloWorld.vue b/web-src/components/HelloWorld.vue deleted file mode 100644 index 893a0ad..0000000 --- a/web-src/components/HelloWorld.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - - - diff --git a/web-src/components/Icon.vue b/web-src/components/Icon.vue new file mode 100644 index 0000000..19ce6a6 --- /dev/null +++ b/web-src/components/Icon.vue @@ -0,0 +1,41 @@ + + + diff --git a/web-src/components/TheWelcome.vue b/web-src/components/TheWelcome.vue deleted file mode 100644 index 786f2af..0000000 --- a/web-src/components/TheWelcome.vue +++ /dev/null @@ -1,97 +0,0 @@ - - - diff --git a/web-src/components/WelcomeItem.vue b/web-src/components/WelcomeItem.vue deleted file mode 100644 index 6d7086a..0000000 --- a/web-src/components/WelcomeItem.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - diff --git a/web-src/components/icons/IconCommunity.vue b/web-src/components/icons/IconCommunity.vue deleted file mode 100644 index 326a7cd..0000000 --- a/web-src/components/icons/IconCommunity.vue +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/web-src/components/icons/IconDocumentation.vue b/web-src/components/icons/IconDocumentation.vue deleted file mode 100644 index 6d6257b..0000000 --- a/web-src/components/icons/IconDocumentation.vue +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/web-src/components/icons/IconEcosystem.vue b/web-src/components/icons/IconEcosystem.vue deleted file mode 100644 index 52e8920..0000000 --- a/web-src/components/icons/IconEcosystem.vue +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/web-src/components/icons/IconSupport.vue b/web-src/components/icons/IconSupport.vue deleted file mode 100644 index b140f87..0000000 --- a/web-src/components/icons/IconSupport.vue +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/web-src/components/icons/IconTooling.vue b/web-src/components/icons/IconTooling.vue deleted file mode 100644 index 188c6fe..0000000 --- a/web-src/components/icons/IconTooling.vue +++ /dev/null @@ -1,17 +0,0 @@ - - diff --git a/web-src/index.html b/web-src/index.html index 1d3e01a..c36dbf2 100644 --- a/web-src/index.html +++ b/web-src/index.html @@ -2,12 +2,12 @@ - - + + Vite App -
- +
+ diff --git a/web-src/layout/Head.vue b/web-src/layout/Head.vue new file mode 100644 index 0000000..a3090cc --- /dev/null +++ b/web-src/layout/Head.vue @@ -0,0 +1,175 @@ + + + diff --git a/web-src/layout/Router.vue b/web-src/layout/Router.vue new file mode 100644 index 0000000..46f2a39 --- /dev/null +++ b/web-src/layout/Router.vue @@ -0,0 +1,15 @@ + + + diff --git a/web-src/layout/index.vue b/web-src/layout/index.vue new file mode 100644 index 0000000..05bc89d --- /dev/null +++ b/web-src/layout/index.vue @@ -0,0 +1,15 @@ + + + diff --git a/web-src/main.ts b/web-src/main.ts index 841d69f..5616dbb 100644 --- a/web-src/main.ts +++ b/web-src/main.ts @@ -1,14 +1,13 @@ -import './assets/main.css'; +import './assets/index.scss'; import { createApp } from 'vue'; -import { createPinia } from 'pinia'; import App from './App.vue'; -import router from './router'; +import { pinia, router } from './plugin'; const app = createApp(App); -app.use(createPinia()); +app.use(pinia); app.use(router); app.mount('#app'); diff --git a/web-src/plugin/alova/index.ts b/web-src/plugin/alova/index.ts new file mode 100644 index 0000000..7f9c0b3 --- /dev/null +++ b/web-src/plugin/alova/index.ts @@ -0,0 +1,47 @@ +import { createAlova } from 'alova'; +import adapterFetch from 'alova/fetch'; +import { message, UseAuthStore } from '@/plugin'; + +export * from './type'; + +export const alovaInstance = createAlova({ + requestAdapter: adapterFetch(), + cacheFor: { expire: 0 }, + responded: async (response) => { + const text = await response.text(); + const data = { + response: () => response, + text: () => text, + json: () => JSON.parse(text), + headers: () => { + const headers: { [key: string]: string } = {}; + response.headers.forEach((k, v) => { + headers[k] = v; + }); + return headers; + }, + }; + if (response.status !== 200) { + const messages = JSON.parse(text).message; + if (response.status === 500) message.error(messages); + throw new RequestError(data, messages); + } + return data; + }, + beforeRequest(method) { + const useAuthStore = UseAuthStore(); + if (useAuthStore.isLogin) { + method.config.headers.Authorization = `Bearer ${useAuthStore.token}`; + } + }, +}); + +export class RequestError extends Error { + public data: any; + + constructor(data: any, message: string) { + super(message); + this.data = data; + this.name = 'RequestError'; + } +} diff --git a/web-src/plugin/alova/type.ts b/web-src/plugin/alova/type.ts new file mode 100644 index 0000000..02ff0cd --- /dev/null +++ b/web-src/plugin/alova/type.ts @@ -0,0 +1,13 @@ +export interface AlovaResponseType { + json: () => ResponseServer; + text: () => string; + response: () => Response; + headers: () => { [key: string]: string }; +} + +export interface ResponseServer { + code: number; + message: string; + data: K; + dateTime: string; +} diff --git a/web-src/plugin/index.ts b/web-src/plugin/index.ts new file mode 100644 index 0000000..34433bc --- /dev/null +++ b/web-src/plugin/index.ts @@ -0,0 +1,11 @@ +import type { MessageApiInjection } from 'naive-ui/es/message/src/MessageProvider'; + +export * from './router'; +export * from './stores'; +export * from './alova'; + +export let message: MessageApiInjection; + +export function setMessage(messages: MessageApiInjection) { + message = messages; +} diff --git a/web-src/plugin/router/index.ts b/web-src/plugin/router/index.ts new file mode 100644 index 0000000..b76a0d5 --- /dev/null +++ b/web-src/plugin/router/index.ts @@ -0,0 +1,25 @@ +import { createRouter, createWebHistory } from 'vue-router'; + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + component: () => import('@/layout/Router.vue'), + children: [ + { + path: '/', + name: 'home', + component: () => import('@/views/HomeView.vue'), + }, + { + path: '/swagger', + name: 'api', + component: () => import('@/views/SwaggerView.vue'), + }, + ], + }, + ], +}); + +export { router }; diff --git a/web-src/plugin/stores/auth.ts b/web-src/plugin/stores/auth.ts new file mode 100644 index 0000000..3001f24 --- /dev/null +++ b/web-src/plugin/stores/auth.ts @@ -0,0 +1,46 @@ +import { defineStore } from 'pinia'; +import { login, woIsMe } from '@/api'; +import { LocalStorageApi } from '@/util'; + +export const UseAuthStore = defineStore('auth', { + state: () => ({ + username: '', + password: '', + isAdmin: false, + isLogin: false, + userId: '', + prermissions: Array(), + roles: Array(), + token: '', + isRemberMe: false, + }), + actions: { + login(username: string, password: string) { + login({ username, password }).then((r) => { + if (this.isRemberMe) { + this.username = username; + this.password = password; + } + this.token = r.json().data; + this.isLogin = true; + this.woIsMe(); + }); + }, + woIsMe() { + if (this.isLogin) + woIsMe() + .then((r) => { + const data = r.json().data; + this.username = data.username; + this.isAdmin = data.admin; + this.prermissions = data.prermissions; + this.roles = data.roles; + this.userId = data.id; + }) + .catch(() => this.$reset()); + }, + }, + persist: { + storage: LocalStorageApi.StorageApi, + }, +}); diff --git a/web-src/plugin/stores/index.ts b/web-src/plugin/stores/index.ts new file mode 100644 index 0000000..5964aec --- /dev/null +++ b/web-src/plugin/stores/index.ts @@ -0,0 +1,8 @@ +import { createPinia } from 'pinia'; +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'; + +export * from './setting'; +export * from './auth.ts'; +const pinia = createPinia(); +pinia.use(piniaPluginPersistedstate); +export { pinia }; diff --git a/web-src/plugin/stores/setting.ts b/web-src/plugin/stores/setting.ts new file mode 100644 index 0000000..3434d22 --- /dev/null +++ b/web-src/plugin/stores/setting.ts @@ -0,0 +1,19 @@ +import { defineStore } from 'pinia'; + +import { useColorMode } from '@vueuse/core'; +import { LocalStorageApi } from '@/util/Cookies.ts'; + +export const UseSettingStore = defineStore('setting', { + state: () => { + const { store, state } = useColorMode(); + return { + themeMode: store, + theme: state, + appName: '', + appVersion: '', + }; + }, + persist: { + storage: LocalStorageApi.StorageApi, + }, +}); diff --git a/web-src/router/index.ts b/web-src/router/index.ts deleted file mode 100644 index f4b2afd..0000000 --- a/web-src/router/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { createRouter, createWebHistory } from 'vue-router'; -import HomeView from '../views/HomeView.vue'; - -const router = createRouter({ - history: createWebHistory(import.meta.env.BASE_URL), - routes: [ - { - path: '/', - name: 'home', - component: HomeView, - }, - { - path: '/about', - name: 'about', - // route level code-splitting - // this generates a separate chunk (About.[hash].js) for this route - // which is lazy-loaded when the route is visited. - component: () => import('../views/AboutView.vue'), - }, - ], -}); - -export default router; diff --git a/web-src/stores/counter.ts b/web-src/stores/counter.ts deleted file mode 100644 index e884e6d..0000000 --- a/web-src/stores/counter.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ref, computed } from 'vue'; -import { defineStore } from 'pinia'; - -export const useCounterStore = defineStore('counter', () => { - const count = ref(0); - const doubleCount = computed(() => count.value * 2); - function increment() { - count.value++; - } - - return { count, doubleCount, increment }; -}); diff --git a/web-src/util/Cookies.ts b/web-src/util/Cookies.ts new file mode 100644 index 0000000..21f7856 --- /dev/null +++ b/web-src/util/Cookies.ts @@ -0,0 +1,57 @@ +import Cookies from 'js-cookie'; +import type { StorageLike } from 'pinia-plugin-persistedstate'; +import { Base64 } from 'js-base64'; + +export const LocalStorageApi: { + Get: (key: string) => string | null; + Set: (key: string, value: string) => void; + StorageApi: StorageLike; +} = { + Get(key: string): string | null { + const data = localStorage.getItem(key); + if (data) { + return Base64.decode(data); + } + return null; + }, + Set(key: string, value: string) { + localStorage.setItem(key, Base64.encode(value)); + }, + StorageApi: { + getItem(key: string) { + return LocalStorageApi.Get(key); + }, + setItem(key: string, value: string) { + LocalStorageApi.Set(key, value); + }, + }, +}; + +const CookiesApi: { + Get: (key: string) => string | null; + Set: (key: string, value: string) => void; + StorageApi: StorageLike; +} = { + Get(key: string): string | null { + const data = Cookies.get(key); + if (data) { + return Base64.decode(data); + } + return null; + }, + Set(key: string, value: string) { + Cookies.set(key, Base64.encode(value), { + expires: 265, + }); + }, + StorageApi: { + getItem(key: string) { + return CookiesApi.Get(key); + }, + setItem(key: string, value: string) { + CookiesApi.Set(key, value); + }, + }, +}; + +export default CookiesApi; diff --git a/web-src/util/UseBoolRef.ts b/web-src/util/UseBoolRef.ts new file mode 100644 index 0000000..95f0477 --- /dev/null +++ b/web-src/util/UseBoolRef.ts @@ -0,0 +1,25 @@ +import { ref } from 'vue'; + +function UseBoolRef(bool?: boolean) { + const data = ref(false); + if (bool) { + data.value = bool; + } + return { + get value() { + return data.value; + }, + set value(v) { + data.value = v; + }, + refdata: data, + on() { + data.value = true; + }, + off() { + data.value = false; + }, + }; +} + +export { UseBoolRef }; diff --git a/web-src/util/index.ts b/web-src/util/index.ts new file mode 100644 index 0000000..4521d3a --- /dev/null +++ b/web-src/util/index.ts @@ -0,0 +1,2 @@ +export * from './UseBoolRef'; +export * from './Cookies'; diff --git a/web-src/views/AboutView.vue b/web-src/views/AboutView.vue deleted file mode 100644 index 756ad2a..0000000 --- a/web-src/views/AboutView.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - diff --git a/web-src/views/HomeView.vue b/web-src/views/HomeView.vue index 0eb7a50..886f3a1 100644 --- a/web-src/views/HomeView.vue +++ b/web-src/views/HomeView.vue @@ -1,9 +1,10 @@ - - + + diff --git a/web-src/views/SwaggerView.vue b/web-src/views/SwaggerView.vue new file mode 100644 index 0000000..2582b42 --- /dev/null +++ b/web-src/views/SwaggerView.vue @@ -0,0 +1,18 @@ + + + -- 2.47.2