diff --git a/README.md b/README.md index 0fe5f96..0dacf24 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ * 手动处理跨域,采用过滤器实现 * 使用Swagger作为接口文档自动生成,已自动配置登录相关接口 * 采用过滤器实现对所有请求自动生成雪花ID方便线上定位问题 +* 针对于多环境进行处理,开发环境和生产环境采用不同的配置 +* 日志中包含单次请求完整信息以及对应的雪花ID,支持文件记录 * 项目整体结构清晰,职责明确,注释全面,开箱即用 ### 前端功能与技术点 diff --git a/my-project-backend/src/main/java/com/example/config/SecurityConfiguration.java b/my-project-backend/src/main/java/com/example/config/SecurityConfiguration.java index 5449614..e61d41d 100644 --- a/my-project-backend/src/main/java/com/example/config/SecurityConfiguration.java +++ b/my-project-backend/src/main/java/com/example/config/SecurityConfiguration.java @@ -108,6 +108,7 @@ public class SecurityConfiguration { writer.write(RestBean.forbidden("登录验证频繁,请稍后再试").asJsonString()); } else { AuthorizeVO vo = account.asViewObject(AuthorizeVO.class, o -> o.setToken(jwt)); + vo.setExpire(utils.expireTime()); writer.write(RestBean.success(vo).asJsonString()); } } diff --git a/my-project-backend/src/main/java/com/example/controller/AuthorizeController.java b/my-project-backend/src/main/java/com/example/controller/AuthorizeController.java index 4c47e74..59ce436 100644 --- a/my-project-backend/src/main/java/com/example/controller/AuthorizeController.java +++ b/my-project-backend/src/main/java/com/example/controller/AuthorizeController.java @@ -1,6 +1,7 @@ package com.example.controller; import com.example.entity.RestBean; +import com.example.entity.vo.request.ConfirmResetVO; import com.example.entity.vo.request.EmailRegisterVO; import com.example.entity.vo.request.EmailResetVO; import com.example.service.AccountService; @@ -9,7 +10,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; -import jakarta.validation.constraints.Email; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -29,13 +29,13 @@ public class AuthorizeController { /** * 请求邮件验证码 - * @param email 邮件 + * @param email 请求邮件 * @param request 请求 * @return 是否请求成功 */ - @PostMapping("/ask-code") + @GetMapping("/ask-code") @Operation(summary = "请求邮件验证码") - public RestBean askVerifyCode(@RequestParam @Email String email, + public RestBean askVerifyCode(@RequestParam String email, HttpServletRequest request){ return this.messageHandle(() -> accountService.registerEmailVerifyCode(String.valueOf(email), request.getRemoteAddr())); @@ -53,6 +53,17 @@ public class AuthorizeController { accountService.registerEmailAccount(vo)); } + /** + * 执行密码重置确认,检查验证码是否正确 + * @param vo 密码重置信息 + * @return 是否操作成功 + */ + @PostMapping("/reset-confirm") + @Operation(summary = "密码重置确认") + public RestBean resetConfirm(@RequestBody @Valid ConfirmResetVO vo){ + return this.messageHandle(() -> accountService.resetConfirm(vo)); + } + /** * 执行密码重置操作 * @param vo 密码重置信息 @@ -60,7 +71,7 @@ public class AuthorizeController { */ @PostMapping("/reset-password") @Operation(summary = "密码重置操作") - public RestBean reset(@RequestBody @Valid EmailResetVO vo){ + public RestBean resetPassword(@RequestBody @Valid EmailResetVO vo){ return this.messageHandle(() -> accountService.resetEmailAccountPassword(vo)); } diff --git a/my-project-backend/src/main/java/com/example/entity/vo/request/ConfirmResetVO.java b/my-project-backend/src/main/java/com/example/entity/vo/request/ConfirmResetVO.java new file mode 100644 index 0000000..e7d8af7 --- /dev/null +++ b/my-project-backend/src/main/java/com/example/entity/vo/request/ConfirmResetVO.java @@ -0,0 +1,15 @@ +package com.example.entity.vo.request; + +import jakarta.validation.constraints.Email; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +@Data +@AllArgsConstructor +public class ConfirmResetVO { + @Email + String email; + @Length(max = 6, min = 6) + String code; +} diff --git a/my-project-backend/src/main/java/com/example/entity/vo/request/EmailRegisterVO.java b/my-project-backend/src/main/java/com/example/entity/vo/request/EmailRegisterVO.java index 2bc6b30..e025b1c 100644 --- a/my-project-backend/src/main/java/com/example/entity/vo/request/EmailRegisterVO.java +++ b/my-project-backend/src/main/java/com/example/entity/vo/request/EmailRegisterVO.java @@ -14,9 +14,9 @@ public class EmailRegisterVO { String email; @Length(max = 6, min = 6) String code; + @Pattern(regexp = "^[a-zA-Z0-9\\u4e00-\\u9fa5]+$") @Length(min = 1, max = 10) String username; @Length(min = 6, max = 20) - @Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*\\d)(?=.*[@#$%^&+=]).*$") String password; } diff --git a/my-project-backend/src/main/java/com/example/entity/vo/request/EmailResetVO.java b/my-project-backend/src/main/java/com/example/entity/vo/request/EmailResetVO.java index e2f9f73..69de696 100644 --- a/my-project-backend/src/main/java/com/example/entity/vo/request/EmailResetVO.java +++ b/my-project-backend/src/main/java/com/example/entity/vo/request/EmailResetVO.java @@ -1,6 +1,7 @@ package com.example.entity.vo.request; import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Pattern; import lombok.Data; import org.hibernate.validator.constraints.Length; @@ -14,6 +15,5 @@ public class EmailResetVO { @Length(max = 6, min = 6) String code; @Length(min = 6, max = 20) - //@Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*\\d)(?=.*[@#$%^&+=]).*$") String password; } diff --git a/my-project-backend/src/main/java/com/example/entity/vo/response/AuthorizeVO.java b/my-project-backend/src/main/java/com/example/entity/vo/response/AuthorizeVO.java index e7673eb..88cd2b3 100644 --- a/my-project-backend/src/main/java/com/example/entity/vo/response/AuthorizeVO.java +++ b/my-project-backend/src/main/java/com/example/entity/vo/response/AuthorizeVO.java @@ -2,6 +2,8 @@ package com.example.entity.vo.response; import lombok.Data; +import java.util.Date; + /** * 登录验证成功的用户信息响应 */ @@ -10,4 +12,5 @@ public class AuthorizeVO { String username; String role; String token; + Date expire; } diff --git a/my-project-backend/src/main/java/com/example/filter/CorsFilter.java b/my-project-backend/src/main/java/com/example/filter/CorsFilter.java index dd92cd4..e0a8827 100644 --- a/my-project-backend/src/main/java/com/example/filter/CorsFilter.java +++ b/my-project-backend/src/main/java/com/example/filter/CorsFilter.java @@ -30,8 +30,8 @@ public class CorsFilter extends HttpFilter { @Override protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { - chain.doFilter(request, response); this.addCorsHeader(request, response); + chain.doFilter(request, response); } /** @@ -40,8 +40,9 @@ public class CorsFilter extends HttpFilter { * @param response 响应 */ private void addCorsHeader(HttpServletRequest request, HttpServletResponse response) { - response.addHeader("Access-Control-Allow-Origin", this.resolveMethod()); - response.addHeader("Access-Control-Allow-Methods", this.resolveOrigin(request)); + response.addHeader("Access-Control-Allow-Origin", this.resolveOrigin(request)); + response.addHeader("Access-Control-Allow-Methods", this.resolveMethod()); + response.addHeader("Access-Control-Allow-Headers", "Authorization, Content-Type"); if(credentials) { response.addHeader("Access-Control-Allow-Credentials", "true"); } @@ -52,7 +53,7 @@ public class CorsFilter extends HttpFilter { * @return 解析得到的请求头值 */ private String resolveMethod(){ - return methods; + return methods.equals("*") ? "GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE, PATCH" : methods; } /** @@ -61,6 +62,6 @@ public class CorsFilter extends HttpFilter { * @return 解析得到的请求头值 */ private String resolveOrigin(HttpServletRequest request){ - return origin; + return origin.equals("*") ? request.getHeader("Origin") : origin; } } diff --git a/my-project-backend/src/main/java/com/example/service/AccountService.java b/my-project-backend/src/main/java/com/example/service/AccountService.java index 432048d..ce8a09d 100644 --- a/my-project-backend/src/main/java/com/example/service/AccountService.java +++ b/my-project-backend/src/main/java/com/example/service/AccountService.java @@ -2,6 +2,7 @@ package com.example.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.entity.dto.Account; +import com.example.entity.vo.request.ConfirmResetVO; import com.example.entity.vo.request.EmailRegisterVO; import com.example.entity.vo.request.EmailResetVO; import org.springframework.security.core.userdetails.UserDetailsService; @@ -11,4 +12,5 @@ public interface AccountService extends IService, UserDetailsService { String registerEmailVerifyCode(String email, String address); String registerEmailAccount(EmailRegisterVO info); String resetEmailAccountPassword(EmailResetVO info); + String resetConfirm(ConfirmResetVO info); } diff --git a/my-project-backend/src/main/java/com/example/service/impl/AccountServiceImpl.java b/my-project-backend/src/main/java/com/example/service/impl/AccountServiceImpl.java index c72ab25..bd1344d 100644 --- a/my-project-backend/src/main/java/com/example/service/impl/AccountServiceImpl.java +++ b/my-project-backend/src/main/java/com/example/service/impl/AccountServiceImpl.java @@ -3,6 +3,7 @@ package com.example.service.impl; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.entity.dto.Account; +import com.example.entity.vo.request.ConfirmResetVO; import com.example.entity.vo.request.EmailRegisterVO; import com.example.entity.vo.request.EmailResetVO; import com.example.mapper.AccountMapper; @@ -10,6 +11,7 @@ import com.example.service.AccountService; import com.example.utils.Const; import com.example.utils.FlowUtils; import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.amqp.core.AmqpTemplate; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.StringRedisTemplate; @@ -115,13 +117,29 @@ public class AccountServiceImpl extends ServiceImpl impl */ @Override public String resetEmailAccountPassword(EmailResetVO info) { + String verify = resetConfirm(new ConfirmResetVO(info.getEmail(), info.getCode())); + if(verify != null) return verify; + String email = info.getEmail(); + String password = passwordEncoder.encode(info.getPassword()); + boolean update = this.update().eq("email", email).set("password", password).update(); + if(update) { + this.deleteEmailVerifyCode(email); + } + return update ? null : "更新失败,请联系管理员"; + } + + /** + * 重置密码确认操作,验证验证码是否正确 + * @param info 验证基本信息 + * @return 操作结果,null表示正常,否则为错误原因 + */ + @Override + public String resetConfirm(ConfirmResetVO info) { String email = info.getEmail(); String code = this.getEmailVerifyCode(email); if(code == null) return "请先获取验证码"; if(!code.equals(info.getCode())) return "验证码错误,请重新输入"; - String password = passwordEncoder.encode(info.getPassword()); - boolean update = this.update().eq("email", email).set("password", password).update(); - return update ? null : "更新失败,请联系管理员"; + return null; } /** diff --git a/my-project-backend/src/main/java/com/example/utils/JwtUtils.java b/my-project-backend/src/main/java/com/example/utils/JwtUtils.java index 5d88428..269f7a8 100644 --- a/my-project-backend/src/main/java/com/example/utils/JwtUtils.java +++ b/my-project-backend/src/main/java/com/example/utils/JwtUtils.java @@ -62,6 +62,16 @@ public class JwtUtils { } } + /** + * 根据配置快速计算过期时间 + * @return 过期时间 + */ + public Date expireTime() { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.HOUR, expire); + return calendar.getTime(); + } + /** * 根据UserDetails生成对应的Jwt令牌 * @param user 用户信息 @@ -70,9 +80,7 @@ public class JwtUtils { public String createJwt(UserDetails user, String username, int userId) { if(this.frequencyCheck(userId)) { Algorithm algorithm = Algorithm.HMAC256(key); - Calendar calendar = Calendar.getInstance(); - Date now = calendar.getTime(); - calendar.add(Calendar.HOUR, expire); + Date expire = this.expireTime(); return JWT.create() .withJWTId(UUID.randomUUID().toString()) .withClaim("id", userId) @@ -80,8 +88,8 @@ public class JwtUtils { .withClaim("authorities", user.getAuthorities() .stream() .map(GrantedAuthority::getAuthority).toList()) - .withExpiresAt(calendar.getTime()) - .withIssuedAt(now) + .withExpiresAt(expire) + .withIssuedAt(new Date()) .sign(algorithm); } else { return null; diff --git a/my-project-frontend/index.html b/my-project-frontend/index.html index 99f583a..f1b1688 100644 --- a/my-project-frontend/index.html +++ b/my-project-frontend/index.html @@ -4,10 +4,16 @@ + Vite App +
- + diff --git a/my-project-frontend/my-project-frontend.iml b/my-project-frontend/my-project-frontend.iml index 8021953..15fa616 100644 --- a/my-project-frontend/my-project-frontend.iml +++ b/my-project-frontend/my-project-frontend.iml @@ -5,5 +5,6 @@ + \ No newline at end of file diff --git a/my-project-frontend/package-lock.json b/my-project-frontend/package-lock.json index 4f4eba6..6407c43 100644 --- a/my-project-frontend/package-lock.json +++ b/my-project-frontend/package-lock.json @@ -8,13 +8,26 @@ "name": "my-project-frontend", "version": "0.0.0", "dependencies": { - "vue": "^3.3.4" + "@element-plus/icons-vue": "^2.1.0", + "@vueuse/core": "^10.3.0", + "axios": "^1.4.0", + "element-plus": "^2.3.9", + "vue": "^3.3.4", + "vue-router": "^4.2.4" }, "devDependencies": { "@vitejs/plugin-vue": "^4.2.3", + "unplugin-auto-import": "^0.15.2", + "unplugin-vue-components": "^0.24.1", "vite": "^4.4.6" } }, + "node_modules/@antfu/utils": { + "version": "0.7.5", + "resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.5.tgz", + "integrity": "sha512-dlR6LdS+0SzOAPx/TPRhnoi7hE251OVeT2Snw0RguNbBSbjUHdWr0l3vcUUDg26rEysT89kCbtw1lVorBXLLCg==", + "dev": true + }, "node_modules/@babel/parser": { "version": "7.22.7", "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.22.7.tgz", @@ -26,6 +39,22 @@ "node": ">=6.0.0" } }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.0.tgz", + "integrity": "sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@element-plus/icons-vue": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz", + "integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==", + "peerDependencies": { + "vue": "^3.2.0" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.18.17", "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.18.17.tgz", @@ -378,11 +407,120 @@ "node": ">=12" } }, + "node_modules/@floating-ui/core": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.4.1.tgz", + "integrity": "sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==", + "dependencies": { + "@floating-ui/utils": "^0.1.1" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.5.1.tgz", + "integrity": "sha512-KwvVcPSXg6mQygvA1TjbN/gh///36kKtllIF8SUm0qpFj8+rvYrpvlYdL1JoA71SHpDqgSSdGOSoQ0Mp3uY5aw==", + "dependencies": { + "@floating-ui/core": "^1.4.1", + "@floating-ui/utils": "^0.1.1" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.1.1.tgz", + "integrity": "sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==" + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.7", + "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.14.196", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.196.tgz", + "integrity": "sha512-22y3o88f4a94mKljsZcanlNWPzO0uBsBdzLAngf2tp533LzZcQzb6+eZPJ+vCTt+bqF2XnvT9gejTLsAcJAJyQ==" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.8", + "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.8.tgz", + "integrity": "sha512-euY3XQcZmIzSy7YH5+Unb3b2X12Wtk54YWINBvvGQ5SmMvwb11JQskGsfkH/5HXK77Kr8GF0wkVDIxzAisWtog==", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.17", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz", + "integrity": "sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA==" + }, "node_modules/@vitejs/plugin-vue": { "version": "4.2.3", "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-4.2.3.tgz", @@ -442,6 +580,11 @@ "@vue/shared": "3.3.4" } }, + "node_modules/@vue/devtools-api": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz", + "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==" + }, "node_modules/@vue/reactivity": { "version": "3.3.4", "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.3.4.tgz", @@ -498,11 +641,320 @@ "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.3.4.tgz", "integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==" }, + "node_modules/@vueuse/core": { + "version": "10.3.0", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-10.3.0.tgz", + "integrity": "sha512-BEM5yxcFKb5btFjTSAFjTu5jmwoW66fyV9uJIP4wUXXU8aR5Hl44gndaaXp7dC5HSObmgbnR2RN+Un1p68Mf5Q==", + "dependencies": { + "@types/web-bluetooth": "^0.0.17", + "@vueuse/metadata": "10.3.0", + "@vueuse/shared": "10.3.0", + "vue-demi": ">=0.14.5" + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.5", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "10.3.0", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-10.3.0.tgz", + "integrity": "sha512-Ema3YhNOa4swDsV0V7CEY5JXvK19JI/o1szFO1iWxdFg3vhdFtCtSTP26PCvbUpnUtNHBY2wx5y3WDXND5Pvnw==" + }, + "node_modules/@vueuse/shared": { + "version": "10.3.0", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-10.3.0.tgz", + "integrity": "sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==", + "dependencies": { + "vue-demi": ">=0.14.5" + } + }, + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.5", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/csstype": { "version": "3.1.2", "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.2.tgz", "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, + "node_modules/dayjs": { + "version": "1.11.9", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.9.tgz", + "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/element-plus": { + "version": "2.3.9", + "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.3.9.tgz", + "integrity": "sha512-TIOLnPl4cnoCPXqK3QYh+jpkthUBQnAM21O7o3Lhbse8v9pfrRXRTaBJtoEKnYNa8GZ4lZptUfH0PeZgDCNLUg==", + "dependencies": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.0.6", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^9.1.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.3", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/element-plus/node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" + }, + "node_modules/element-plus/node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "dependencies": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + } + }, + "node_modules/element-plus/node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.5", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/element-plus/node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==" + }, + "node_modules/element-plus/node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "dependencies": { + "vue-demi": "*" + } + }, + "node_modules/element-plus/node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.5", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/esbuild": { "version": "0.18.17", "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.18.17.tgz", @@ -540,11 +992,88 @@ "@esbuild/win32-x64": "0.18.17" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz", @@ -559,6 +1088,122 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/local-pkg": { + "version": "0.4.3", + "resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.4.3.tgz", + "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, "node_modules/magic-string": { "version": "0.30.2", "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.2.tgz", @@ -570,6 +1215,82 @@ "node": ">=12" } }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mlly": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.4.0.tgz", + "integrity": "sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "pathe": "^1.1.1", + "pkg-types": "^1.0.3", + "ufo": "^1.1.2" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/nanoid": { "version": "3.3.6", "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.6.tgz", @@ -581,11 +1302,57 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==" + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/pathe": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.1.tgz", + "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==", + "dev": true + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/pkg-types": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.0.3.tgz", + "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.2.0", + "pathe": "^1.1.0" + } + }, "node_modules/postcss": { "version": "8.4.27", "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.27.tgz", @@ -599,6 +1366,53 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.4", + "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rollup": { "version": "3.27.0", "resolved": "https://registry.npmmirror.com/rollup/-/rollup-3.27.0.tgz", @@ -615,6 +1429,21 @@ "fsevents": "~2.3.2" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scule": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/scule/-/scule-1.0.0.tgz", + "integrity": "sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ==", + "dev": true + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz", @@ -623,6 +1452,149 @@ "node": ">=0.10.0" } }, + "node_modules/strip-literal": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/strip-literal/-/strip-literal-1.3.0.tgz", + "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==", + "dev": true, + "dependencies": { + "acorn": "^8.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ufo": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.2.0.tgz", + "integrity": "sha512-RsPyTbqORDNDxqAdQPQBpgqhWle1VcTSou/FraClYlHf6TZnQcGslpLcAphNR+sQW4q5lLWLbOsRlh9j24baQg==", + "dev": true + }, + "node_modules/unimport": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/unimport/-/unimport-3.1.3.tgz", + "integrity": "sha512-up4TE2yA+nMyyErGTjbYGVw95MriGa2hVRXQ3/JRp7984cwwqULcnBjHaovVpsO8tZc2j0fvgGu9yiBKOyxvYw==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.2", + "escape-string-regexp": "^5.0.0", + "fast-glob": "^3.3.1", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.2", + "mlly": "^1.4.0", + "pathe": "^1.1.1", + "pkg-types": "^1.0.3", + "scule": "^1.0.0", + "strip-literal": "^1.3.0", + "unplugin": "^1.4.0" + } + }, + "node_modules/unplugin": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/unplugin/-/unplugin-1.4.0.tgz", + "integrity": "sha512-5x4eIEL6WgbzqGtF9UV8VEC/ehKptPXDS6L2b0mv4FRMkJxRtjaJfOWDd6a8+kYbqsjklix7yWP0N3SUepjXcg==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "chokidar": "^3.5.3", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.5.0" + } + }, + "node_modules/unplugin-auto-import": { + "version": "0.15.3", + "resolved": "https://registry.npmmirror.com/unplugin-auto-import/-/unplugin-auto-import-0.15.3.tgz", + "integrity": "sha512-RLT8SqbPn4bT7yBshZId0uPSofKWnwr66RyDaxWaFb/+f7OTDOWAsVNz+hOQLBWSjvbekr2xZY9ccS8TDHJbCQ==", + "dev": true, + "dependencies": { + "@antfu/utils": "^0.7.2", + "@rollup/pluginutils": "^5.0.2", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.0", + "minimatch": "^9.0.0", + "unimport": "^3.0.6", + "unplugin": "^1.3.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@nuxt/kit": "^3.2.2", + "@vueuse/core": "*" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + }, + "@vueuse/core": { + "optional": true + } + } + }, + "node_modules/unplugin-vue-components": { + "version": "0.24.1", + "resolved": "https://registry.npmmirror.com/unplugin-vue-components/-/unplugin-vue-components-0.24.1.tgz", + "integrity": "sha512-T3A8HkZoIE1Cja95xNqolwza0yD5IVlgZZ1PVAGvVCx8xthmjsv38xWRCtHtwl+rvZyL9uif42SRkDGw9aCfMA==", + "dev": true, + "dependencies": { + "@antfu/utils": "^0.7.2", + "@rollup/pluginutils": "^5.0.2", + "chokidar": "^3.5.3", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.0", + "minimatch": "^7.4.2", + "resolve": "^1.22.1", + "unplugin": "^1.1.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@babel/parser": "^7.15.8", + "@nuxt/kit": "^3.2.2", + "vue": "2 || 3" + }, + "peerDependenciesMeta": { + "@babel/parser": { + "optional": true + }, + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/unplugin-vue-components/node_modules/minimatch": { + "version": "7.4.6", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/vite": { "version": "4.4.8", "resolved": "https://registry.npmmirror.com/vite/-/vite-4.4.8.tgz", @@ -686,6 +1658,32 @@ "@vue/server-renderer": "3.3.4", "@vue/shared": "3.3.4" } + }, + "node_modules/vue-router": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.2.4.tgz", + "integrity": "sha512-9PISkmaCO02OzPVOMq2w82ilty6+xJmQrarYZDkjZBfl4RvYAlt4PKnEX21oW4KTtWfa9OuO/b3qk1Od3AEdCQ==", + "dependencies": { + "@vue/devtools-api": "^6.5.0" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.5.0", + "resolved": "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", + "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", + "dev": true } } } diff --git a/my-project-frontend/package.json b/my-project-frontend/package.json index dab65b9..8c3ce73 100644 --- a/my-project-frontend/package.json +++ b/my-project-frontend/package.json @@ -8,10 +8,17 @@ "preview": "vite preview" }, "dependencies": { - "vue": "^3.3.4" + "@element-plus/icons-vue": "^2.1.0", + "@vueuse/core": "^10.3.0", + "axios": "^1.4.0", + "element-plus": "^2.3.9", + "vue": "^3.3.4", + "vue-router": "^4.2.4" }, "devDependencies": { "@vitejs/plugin-vue": "^4.2.3", + "unplugin-auto-import": "^0.15.2", + "unplugin-vue-components": "^0.24.1", "vite": "^4.4.6" } } diff --git a/my-project-frontend/src/App.vue b/my-project-frontend/src/App.vue index 633a5df..2ca210c 100644 --- a/my-project-frontend/src/App.vue +++ b/my-project-frontend/src/App.vue @@ -1,47 +1,29 @@ diff --git a/my-project-frontend/src/assets/base.css b/my-project-frontend/src/assets/base.css deleted file mode 100644 index d3de42e..0000000 --- a/my-project-frontend/src/assets/base.css +++ /dev/null @@ -1,73 +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/my-project-frontend/src/assets/logo.svg b/my-project-frontend/src/assets/logo.svg deleted file mode 100644 index 7565660..0000000 --- a/my-project-frontend/src/assets/logo.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/my-project-frontend/src/assets/main.css b/my-project-frontend/src/assets/main.css deleted file mode 100644 index e8667cd..0000000 --- a/my-project-frontend/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; -} - -@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/my-project-frontend/src/components/HelloWorld.vue b/my-project-frontend/src/components/HelloWorld.vue deleted file mode 100644 index 5fb372c..0000000 --- a/my-project-frontend/src/components/HelloWorld.vue +++ /dev/null @@ -1,44 +0,0 @@ - - - - - diff --git a/my-project-frontend/src/components/TheWelcome.vue b/my-project-frontend/src/components/TheWelcome.vue deleted file mode 100644 index 5e64625..0000000 --- a/my-project-frontend/src/components/TheWelcome.vue +++ /dev/null @@ -1,86 +0,0 @@ - - - diff --git a/my-project-frontend/src/components/WelcomeItem.vue b/my-project-frontend/src/components/WelcomeItem.vue deleted file mode 100644 index 6d7086a..0000000 --- a/my-project-frontend/src/components/WelcomeItem.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - diff --git a/my-project-frontend/src/components/icons/IconCommunity.vue b/my-project-frontend/src/components/icons/IconCommunity.vue deleted file mode 100644 index 2dc8b05..0000000 --- a/my-project-frontend/src/components/icons/IconCommunity.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/my-project-frontend/src/components/icons/IconDocumentation.vue b/my-project-frontend/src/components/icons/IconDocumentation.vue deleted file mode 100644 index 6d4791c..0000000 --- a/my-project-frontend/src/components/icons/IconDocumentation.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/my-project-frontend/src/components/icons/IconEcosystem.vue b/my-project-frontend/src/components/icons/IconEcosystem.vue deleted file mode 100644 index c3a4f07..0000000 --- a/my-project-frontend/src/components/icons/IconEcosystem.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/my-project-frontend/src/components/icons/IconSupport.vue b/my-project-frontend/src/components/icons/IconSupport.vue deleted file mode 100644 index 7452834..0000000 --- a/my-project-frontend/src/components/icons/IconSupport.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/my-project-frontend/src/components/icons/IconTooling.vue b/my-project-frontend/src/components/icons/IconTooling.vue deleted file mode 100644 index 660598d..0000000 --- a/my-project-frontend/src/components/icons/IconTooling.vue +++ /dev/null @@ -1,19 +0,0 @@ - - diff --git a/my-project-frontend/src/main.js b/my-project-frontend/src/main.js index 0ac3a5f..c6c064a 100644 --- a/my-project-frontend/src/main.js +++ b/my-project-frontend/src/main.js @@ -1,6 +1,14 @@ -import './assets/main.css' - import { createApp } from 'vue' import App from './App.vue' +import router from './router' +import axios from "axios"; -createApp(App).mount('#app') +import 'element-plus/theme-chalk/dark/css-vars.css' + +axios.defaults.baseURL = 'http://localhost:8080' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/my-project-frontend/src/net/index.js b/my-project-frontend/src/net/index.js new file mode 100644 index 0000000..caf2362 --- /dev/null +++ b/my-project-frontend/src/net/index.js @@ -0,0 +1,102 @@ +import axios from "axios"; +import {ElMessage} from "element-plus"; + +const authItemName = "authorize" + +const accessHeader = () => { + return { + 'Authorization': `Bearer ${takeAccessToken()}` + } +} + +const defaultError = (error) => { + console.error(error) + ElMessage.error('发生了一些错误,请联系管理员') +} + +const defaultFailure = (message, status, url) => { + console.warn(`请求地址: ${url}, 状态码: ${status}, 错误信息: ${message}`) + ElMessage.warning(message) +} + +function takeAccessToken() { + const str = localStorage.getItem(authItemName) || sessionStorage.getItem(authItemName); + if(!str) return null + const authObj = JSON.parse(str) + if(authObj.expire <= new Date()) { + deleteAccessToken() + ElMessage.warning("登录状态已过期,请重新登录!") + return null + } + return authObj.token +} + +function storeAccessToken(remember, token, expire){ + const authObj = { + token: token, + expire: expire + } + const str = JSON.stringify(authObj) + if(remember) + localStorage.setItem(authItemName, str) + else + sessionStorage.setItem(authItemName, str) +} + +function deleteAccessToken() { + localStorage.removeItem(authItemName) + sessionStorage.removeItem(authItemName) +} + +function internalPost(url, data, headers, success, failure, error = defaultError){ + axios.post(url, data, { headers: headers }).then(({data}) => { + if(data.code === 200) + success(data.data) + else + failure(data.message, data.code, url) + }).catch(err => error(err)) +} + +function internalGet(url, headers, success, failure, error = defaultError){ + axios.get(url, { headers: headers }).then(({data}) => { + if(data.code === 200) + success(data.data) + else + failure(data.message, data.code, url) + }).catch(err => error(err)) +} + +function login(username, password, remember, success, failure = defaultFailure){ + internalPost('/api/auth/login', { + username: username, + password: password + }, { + 'Content-Type': 'application/x-www-form-urlencoded' + }, (data) => { + storeAccessToken(remember, data.token) + ElMessage.success(`登录成功,欢迎 ${data.username} 来到我们的系统`) + success(data) + }, failure) +} + +function post(url, data, success, failure = defaultFailure) { + internalPost(url, data, accessHeader() , success, failure) +} + +function logout(success, failure = defaultFailure){ + get('/api/auth/logout', () => { + deleteAccessToken() + ElMessage.success(`退出登录成功,欢迎您再次使用`) + success() + }, failure) +} + +function get(url, success, failure) { + internalGet(url, accessHeader(), success, failure = defaultFailure) +} + +function unauthorized() { + return !takeAccessToken() +} + +export { post, get, login, logout, unauthorized } diff --git a/my-project-frontend/src/router/index.js b/my-project-frontend/src/router/index.js new file mode 100644 index 0000000..18069ec --- /dev/null +++ b/my-project-frontend/src/router/index.js @@ -0,0 +1,45 @@ +import { createRouter, createWebHistory } from 'vue-router' +import { unauthorized } from "@/net"; + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'welcome', + component: () => import('@/views/WelcomeView.vue'), + children: [ + { + path: '', + name: 'welcome-login', + component: () => import('@/views/welcome/LoginPage.vue') + }, { + path: 'register', + name: 'welcome-register', + component: () => import('@/views/welcome/RegisterPage.vue') + }, { + path: 'forget', + name: 'welcome-forget', + component: () => import('@/views/welcome/ForgetPage.vue') + } + ] + }, { + path: '/index', + name: 'index', + component: () => import('@/views/IndexView.vue'), + } + ] +}) + +router.beforeEach((to, from, next) => { + const isUnauthorized = unauthorized() + if(to.name.startsWith('welcome') && !isUnauthorized) { + next('/index') + } else if(to.fullPath.startsWith('/index') && isUnauthorized) { + next('/') + } else { + next() + } +}) + +export default router diff --git a/my-project-frontend/src/views/IndexView.vue b/my-project-frontend/src/views/IndexView.vue new file mode 100755 index 0000000..8b2ca58 --- /dev/null +++ b/my-project-frontend/src/views/IndexView.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/my-project-frontend/src/views/WelcomeView.vue b/my-project-frontend/src/views/WelcomeView.vue new file mode 100755 index 0000000..bdf0d83 --- /dev/null +++ b/my-project-frontend/src/views/WelcomeView.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/my-project-frontend/src/views/welcome/ForgetPage.vue b/my-project-frontend/src/views/welcome/ForgetPage.vue new file mode 100755 index 0000000..aa9dc6b --- /dev/null +++ b/my-project-frontend/src/views/welcome/ForgetPage.vue @@ -0,0 +1,173 @@ + + + + + diff --git a/my-project-frontend/src/views/welcome/LoginPage.vue b/my-project-frontend/src/views/welcome/LoginPage.vue new file mode 100755 index 0000000..df270a5 --- /dev/null +++ b/my-project-frontend/src/views/welcome/LoginPage.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/my-project-frontend/src/views/welcome/RegisterPage.vue b/my-project-frontend/src/views/welcome/RegisterPage.vue new file mode 100755 index 0000000..d67b366 --- /dev/null +++ b/my-project-frontend/src/views/welcome/RegisterPage.vue @@ -0,0 +1,163 @@ + + + + + diff --git a/my-project-frontend/vite.config.js b/my-project-frontend/vite.config.js index 5c45e1d..b593f61 100644 --- a/my-project-frontend/vite.config.js +++ b/my-project-frontend/vite.config.js @@ -2,11 +2,20 @@ import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' +import AutoImport from 'unplugin-auto-import/vite' +import Components from 'unplugin-vue-components/vite' +import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), + AutoImport({ + resolvers: [ElementPlusResolver()], + }), + Components({ + resolvers: [ElementPlusResolver()], + }), ], resolve: { alias: {