فهرست منبع

Initial commit

PUGE 8 ماه پیش
کامیت
05d6f7da02
100فایلهای تغییر یافته به همراه15408 افزوده شده و 0 حذف شده
  1. BIN
      .DS_Store
  2. 120 0
      .dockerignore
  3. 2 0
      .gitattributes
  4. 4 0
      .gitignore
  5. 7 0
      .vscode/settings.json
  6. 94 0
      Dockerfile
  7. BIN
      EdgeOne.png
  8. 21 0
      LICENSE
  9. 229 0
      README.md
  10. 291 0
      deploy-2c2g.md
  11. 99 0
      docker-compose.low-memory.yml
  12. 63 0
      docker-compose.yml
  13. 233 0
      docker-deploy.md
  14. 68 0
      env.example
  15. 134 0
      nginx.conf
  16. 478 0
      postgreSQL/Internalization.sql
  17. 54 0
      postgreSQL/Log.sql
  18. 136 0
      postgreSQL/Menu.sql
  19. 37 0
      postgreSQL/Message.sql
  20. 62 0
      postgreSQL/MessageRead.sql
  21. 86 0
      postgreSQL/Organization.sql
  22. 187 0
      postgreSQL/Permission.sql
  23. 71 0
      postgreSQL/Post.sql
  24. 55 0
      postgreSQL/Role.sql
  25. 84 0
      postgreSQL/User.sql
  26. 655 0
      postgreSQL/public.sql
  27. 24 0
      server/.eslintrc.js
  28. 57 0
      server/.gitignore
  29. 10 0
      server/.prettierrc
  30. 73 0
      server/README.md
  31. 8 0
      server/nest-cli.json
  32. 104 0
      server/package.json
  33. 6754 0
      server/pnpm-lock.yaml
  34. 8 0
      server/pnpm-workspace.yaml
  35. 242 0
      server/prisma/migrations/20241031011215_init/migration.sql
  36. 29 0
      server/prisma/migrations/20250802123530_add_product_model/migration.sql
  37. 3 0
      server/prisma/migrations/migration_lock.toml
  38. 238 0
      server/prisma/schema.prisma
  39. 56 0
      server/src/app.module.ts
  40. 68 0
      server/src/config/winston.config.ts
  41. 34 0
      server/src/dto/params.dto.ts
  42. 32 0
      server/src/dto/response.dto.ts
  43. 38 0
      server/src/enums/index.ts
  44. 26 0
      server/src/filter/all-exception.filter.ts
  45. 27 0
      server/src/filter/http-exception.filter.ts
  46. 22 0
      server/src/interceptor/logger.interceptor.ts
  47. 75 0
      server/src/main.ts
  48. 45 0
      server/src/middleware/logger.middleware.ts
  49. 23 0
      server/src/middleware/request.middleware.ts
  50. 141 0
      server/src/modules/activation-code/activation-code.controller.ts
  51. 15 0
      server/src/modules/activation-code/activation-code.module.ts
  52. 503 0
      server/src/modules/activation-code/activation-code.service.ts
  53. 42 0
      server/src/modules/activation-code/dto/batch-import-activation-code.dto.ts
  54. 35 0
      server/src/modules/activation-code/dto/export-activation-code.dto.ts
  55. 98 0
      server/src/modules/activation-code/dto/params-activation-code.dto.ts
  56. 17 0
      server/src/modules/activation-code/dto/refund-activation-code.dto.ts
  57. 66 0
      server/src/modules/activation-code/dto/response-activation-code.dto.ts
  58. 102 0
      server/src/modules/activation-code/dto/save-activation-code.dto.ts
  59. 8 0
      server/src/modules/activation-code/enums/index.ts
  60. 61 0
      server/src/modules/administrative/message/dto/params-message.dto.ts
  61. 193 0
      server/src/modules/administrative/message/dto/response-message.dto.ts
  62. 55 0
      server/src/modules/administrative/message/dto/save-message.dto.ts
  63. 165 0
      server/src/modules/administrative/message/message.controller.ts
  64. 22 0
      server/src/modules/administrative/message/message.module.ts
  65. 232 0
      server/src/modules/administrative/message/message.service.ts
  66. 27 0
      server/src/modules/administrative/organazation/dto/params-organazation.dto.ts
  67. 59 0
      server/src/modules/administrative/organazation/dto/response-organazation.dto.ts
  68. 58 0
      server/src/modules/administrative/organazation/dto/save-organazation.dto.ts
  69. 93 0
      server/src/modules/administrative/organazation/organazation.controller.ts
  70. 22 0
      server/src/modules/administrative/organazation/organazation.module.ts
  71. 127 0
      server/src/modules/administrative/organazation/organazation.service.ts
  72. 50 0
      server/src/modules/administrative/post-manage/dto/params-post.dto.ts
  73. 96 0
      server/src/modules/administrative/post-manage/dto/response-post.dto.ts
  74. 59 0
      server/src/modules/administrative/post-manage/dto/save-post.dto.ts
  75. 93 0
      server/src/modules/administrative/post-manage/post-manage.controller.ts
  76. 22 0
      server/src/modules/administrative/post-manage/post-manage.module.ts
  77. 135 0
      server/src/modules/administrative/post-manage/post-manage.service.ts
  78. 197 0
      server/src/modules/auth/auth.controller.ts
  79. 38 0
      server/src/modules/auth/auth.module.ts
  80. 328 0
      server/src/modules/auth/auth.service.ts
  81. 80 0
      server/src/modules/auth/dto/params-auth.dto.ts
  82. 67 0
      server/src/modules/auth/dto/response-auth.dto.ts
  83. 48 0
      server/src/modules/auth/jwt.strategy.ts
  84. 77 0
      server/src/modules/code-type/code-type.controller.ts
  85. 15 0
      server/src/modules/code-type/code-type.module.ts
  86. 136 0
      server/src/modules/code-type/code-type.service.ts
  87. 41 0
      server/src/modules/code-type/dto/params-code-type.dto.ts
  88. 29 0
      server/src/modules/code-type/dto/response-code-type.dto.ts
  89. 16 0
      server/src/modules/code-type/dto/save-code-type.dto.ts
  90. 40 0
      server/src/modules/file-upload/dto/index.ts
  91. 47 0
      server/src/modules/file-upload/file-upload.controller.ts
  92. 63 0
      server/src/modules/file-upload/file-upload.module.ts
  93. 11 0
      server/src/modules/file-upload/file-upload.service.ts
  94. 16 0
      server/src/modules/prisma/prisma.module.ts
  95. 25 0
      server/src/modules/prisma/prisma.service.ts
  96. 47 0
      server/src/modules/system-manage/internalization/dto/params-internalization.dto.ts
  97. 59 0
      server/src/modules/system-manage/internalization/dto/response-internalization.dto.ts
  98. 61 0
      server/src/modules/system-manage/internalization/dto/save-internalization.dto.ts
  99. 83 0
      server/src/modules/system-manage/internalization/internalization.controller.ts
  100. 22 0
      server/src/modules/system-manage/internalization/internalization.module.ts

BIN
.DS_Store


+ 120 - 0
.dockerignore

@@ -0,0 +1,120 @@
+# 依赖目录
+**/node_modules
+**/npm-debug.log*
+**/yarn-debug.log*
+**/yarn-error.log*
+**/pnpm-debug.log*
+
+# 构建输出
+**/dist
+# 注意:保留 web/build 目录(Vite 配置文件)
+server/build
+**/.next
+**/.nuxt
+**/.vuepress/dist
+
+# 开发和测试文件
+**/.vscode
+**/.idea
+**/coverage
+**/test
+**/*.test.js
+**/*.test.ts
+**/*.spec.js
+**/*.spec.ts
+**/jest.config.js
+**/cypress
+**/.nyc_output
+
+# 日志文件
+**/logs
+**/*.log
+**/log
+
+# 运行时数据
+**/pids
+**/*.pid
+**/*.seed
+**/*.pid.lock
+
+# 可选npm缓存目录
+**/.npm
+
+# 可选yarn缓存目录
+**/.yarn-integrity
+
+# dotenv环境变量文件
+# 保留构建和运行需要的环境变量文件
+# **/.env
+**/.env.local
+**/.env.development.local
+**/.env.test.local
+**/.env.production.local
+# 注意:在生产环境中,应通过 docker-compose 或环境变量注入来设置敏感信息
+
+# parcel-bundler缓存目录
+**/.cache
+**/.parcel-cache
+
+# next.js构建输出
+**/.next
+
+# nuxt.js构建输出
+**/.nuxt
+
+# vuepress构建输出
+**/.vuepress/dist
+
+# Serverless目录
+**/.serverless
+
+# FuseBox缓存
+**/.fusebox/
+
+# DynamoDB本地文件
+**/.dynamodb/
+
+# MacOS
+**/.DS_Store
+
+# Windows
+**/Thumbs.db
+**/ehthumbs.db
+**/Desktop.ini
+
+# Linux
+**/*~
+
+# Git
+**/.git
+**/.gitignore
+**/README.md
+
+# Docker
+**/Dockerfile*
+**/docker-compose*
+**/.dockerignore
+
+# 上传的文件(开发环境)
+**/upload
+
+# 临时文件
+**/tmp
+**/temp
+
+# 编辑器配置
+**/.editorconfig
+**/.eslintrc*
+**/.prettierrc*
+
+# TypeScript
+**/tsconfig.json
+
+# 数据库相关
+**/prisma/dev.db*
+**/prisma/migrations
+
+# Lock files (保留package.json但排除锁文件重复)
+# 注意:我们在Dockerfile中单独复制了锁文件
+# **/package-lock.json
+# **/yarn.lock 

+ 2 - 0
.gitattributes

@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+/*.rar
+/Xmw_web/*.rar
+/Xmw_web/*.zip
+.idea

+ 7 - 0
.vscode/settings.json

@@ -0,0 +1,7 @@
+{
+  "vsicons.presets.nestjs": true,
+  "editor.codeActionsOnSave": {
+    "source.fixAll.eslint": "explicit"
+  },
+  "editor.defaultFormatter": "esbenp.prettier-vscode"
+}

+ 94 - 0
Dockerfile

@@ -0,0 +1,94 @@
+# 多阶段构建 Dockerfile
+
+# 阶段1: 构建前端
+FROM node:20-alpine AS frontend-builder
+
+# 设置工作目录
+WORKDIR /app/web
+
+# 安装 pnpm
+RUN npm install -g pnpm
+
+# 复制前端 package.json 和 pnpm-lock.yaml
+COPY web/package.json web/pnpm-lock.yaml ./
+
+# 复制 packages 目录(前端依赖的内部包)
+COPY web/packages ./packages
+
+# 安装前端依赖
+RUN pnpm install 
+
+# 复制前端源代码
+COPY web/ .
+
+# 构建前端应用
+RUN pnpm run build
+
+# 阶段2: 构建后端
+FROM node:20-alpine AS backend-builder
+
+# 设置工作目录
+WORKDIR /app/server
+
+# 安装 pnpm
+RUN npm install -g pnpm
+
+# 复制后端 package.json 和 pnpm-lock.yaml
+COPY server/package.json server/pnpm-lock.yaml ./
+
+# 安装后端依赖
+RUN pnpm install
+
+# 复制后端源代码
+COPY server/ .
+
+# 生成 Prisma 客户端
+RUN npx prisma generate
+
+# 构建后端应用
+RUN pnpm run build
+
+# 阶段3: 生产环境镜像
+FROM node:20-alpine AS production
+
+# 安装必要的系统依赖
+RUN apk add --no-cache nginx
+
+# 设置工作目录
+WORKDIR /app
+
+# 安装 pnpm
+RUN npm install -g pnpm
+
+# 复制后端构建产物和依赖
+COPY --from=backend-builder /app/server/dist ./server/dist
+COPY --from=backend-builder /app/server/node_modules ./server/node_modules
+COPY --from=backend-builder /app/server/package.json ./server/
+COPY --from=backend-builder /app/server/prisma ./server/prisma
+
+# 复制前端构建产物
+COPY --from=frontend-builder /app/web/dist ./web/dist
+
+# 复制 Nginx 配置
+COPY nginx.conf /etc/nginx/nginx.conf
+
+# 创建必要的目录
+RUN mkdir -p /var/log/nginx /var/lib/nginx/body /var/lib/nginx/fastcgi \
+    && mkdir -p /app/server/upload
+
+# 创建启动脚本
+RUN echo '#!/bin/sh' > /app/start.sh && \
+    echo 'cd /app/server' >> /app/start.sh && \
+    echo 'npx prisma migrate deploy' >> /app/start.sh && \
+    echo 'nginx -g "daemon off;" &' >> /app/start.sh && \
+    echo 'node dist/main.js' >> /app/start.sh && \
+    chmod +x /app/start.sh
+
+# 暴露端口
+EXPOSE 80 6666
+
+# 设置环境变量
+ENV NODE_ENV=production
+
+# 启动应用
+CMD ["/app/start.sh"] 

BIN
EdgeOne.png


+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 baiwumm
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 229 - 0
README.md

@@ -0,0 +1,229 @@
+<div align="center">
+  <img width="120" src="./web/public/logo.png" alt="Vue3 Admin">
+  <h1>Vue3 Admin</h1>
+  <p>前端的全栈之路 - 现代化后台管理系统解决方案</p>
+  
+  <p>
+    <a href="https://github.com/baiwumm/vue3-admin/stargazers"><img src="https://img.shields.io/github/stars/baiwumm/vue3-admin" alt="stars"></a>
+    <img src="https://img.shields.io/badge/Vue-3.5-brightgreen" alt="Vue">
+    <img src="https://img.shields.io/badge/Pinia-latest-orange" alt="Pinia">
+    <img src="https://img.shields.io/badge/Nest.js-latest-red" alt="Nest.js">
+    <img src="https://img.shields.io/badge/PostgreSQL-latest-blue" alt="PostgreSQL">
+    <a href="https://github.com/baiwumm/vue3-admin/blob/main/LICENSE"><img src="https://img.shields.io/github/license/baiwumm/vue3-admin" alt="license"></a>
+  </p>
+</div>
+
+## 📚 项目简介
+[Vue3 Admin](https://vue3.baiwumm.com/) 是一个现代化的全栈后台管理系统,前端基于 [Soybean Admin](https://docs.soybeanjs.cn/) 二次开发,后端采用 [Nest.js](https://nestjs.com/) 构建。本项目集成了当前流行的前后端技术栈,是学习全栈开发的理想参考项目。
+
+### 🚀 技术栈
+- **前端**:[Vue 3.5](https://cn.vuejs.org/)、[Ant Design Vue](https://www.antdv.com/)、[UnoCSS](https://unocss.dev/)、[Pinia](https://pinia.vuejs.org/)
+- **后端**:[Nest.js](https://nestjs.com/)、[PostgreSQL](https://www.postgresql.org/)、[Prisma](https://prisma.yoga/)
+
+### 🔗 快速链接
+- 📌 **在线预览**:[https://vue3.baiwumm.com/](https://vue3.baiwumm.com/)
+- 🔑 **测试账号**:用户名 `Admin`,密码 `abc123456`
+- 📝 **API文档**:[Swagger 接口文档](https://vue3.baiwumm.com/docs)
+
+> ❤️ 如果这个项目对你有帮助,请给个 Star 支持作者,感谢!
+
+## ✨ 系统特性
+- **🌐 动态国际化**:支持多语言配置,轻松切换不同语言环境
+- **📝 操作日志记录**:自动记录用户的 CRUD 操作,方便追踪和审计
+- **🔐 完善的权限系统**:用户与角色的精确映射,基于角色动态生成路由菜单
+- **📢 实时消息通知**:基于 SSE (Server-Sent Events) 的消息公告推送系统
+- **🧩 丰富的业务组件**:集成多种实用的业务功能和交互效果
+- **🎨 现代化 UI 设计**:基于 Ant Design Vue 的美观界面,提供良好的用户体验
+
+## 🔧 环境要求
+> 💡 推荐使用 [pnpm](https://pnpm.io/zh/) 作为包管理工具
+
+| 依赖项 | 最低版本 | 推荐版本 | 说明 |
+|--------|---------|---------|------|
+| [Node.js](https://nodejs.org/) | 18.12.0 | 18.19.0+ | JavaScript 运行环境 |
+| [Pnpm](https://pnpm.io/zh/) | 8.7.0 | 最新版 | 高效的包管理工具 |
+| [Git](https://git-scm.com/) | - | 最新版 | 版本控制工具 |
+| [PostgreSQL](https://www.postgresql.org/) | - | 最新版 | 关系型数据库 |
+
+## 🚀 快速开始
+
+### 1. 数据库配置
+```bash
+# 安装 PostgreSQL 数据库
+# 导入 /postgreSQL 目录中的数据文件
+# 修改 /server/.env 文件中的数据库连接配置
+DATABASE_URL="postgresql://postgres:123456@localhost:5432/vue3-admin?schema=public"
+```
+
+### 2. 克隆项目
+```bash
+# 克隆仓库
+git clone https://github.com/baiwumm/vue3-admin.git
+cd vue3-admin
+```
+
+### 3. 安装依赖
+```bash
+# 全局安装 pnpm (如果尚未安装)
+npm install -g pnpm
+
+# 前端依赖安装
+cd web
+pnpm install
+
+# 后端依赖安装
+cd ../server
+pnpm install
+```
+
+### 4. 开发模式
+```bash
+# 前端开发服务
+cd web
+pnpm dev
+
+# 后端开发服务
+cd server
+pnpm start:dev
+```
+
+### 5. 构建项目
+```bash
+# 前端构建
+cd web
+pnpm build
+
+# 后端构建
+cd server
+pnpm build
+```
+
+## 📋 新增路由菜单指南
+
+1. **创建视图文件**
+   - 在 `web/src/views` 目录下新建 `文件夹/index.vue` 文件
+
+2. **配置国际化路由**
+   - 进入系统 → 系统管理 → 国际化 → route
+   - 添加对应的路由配置
+
+3. **添加菜单项**
+   - 进入系统 → 系统管理 → 菜单管理
+   - 按照规则添加新菜单
+   - 路由配置参考:[Soybean Admin 系统路由文档](https://docs.soybeanjs.cn/zh/guide/router/intro.html)
+
+4. **分配权限**
+   - 进入系统 → 系统管理 → 角色管理
+   - 在编辑状态中为相应角色勾选新增的菜单
+   - 保存并刷新页面,新菜单将会生效
+
+## 📚 功能模块
+
+```
+- 登录 / 注销
+
+- 首页
+
+- 智能行政
+  - 消息公告
+  - 组织管理
+  - 岗位管理
+  - 组织架构
+
+- 个人中心
+
+- 功能页
+  - 验证码
+  - 打印
+  - 拾色器
+  - 甘特图
+  - 图片预览
+  - 自定义 Vue 指令
+  - 懒加载
+  - 图片取色盘
+  - 系统级取色器
+  - 文件预览
+  - 流程图
+  - 瀑布流
+  - Swiper
+
+- 技术文档
+  - Soybean(内链)
+  - Vue3
+  - Nest.js
+  - Ant Design Vue
+  - UnoCSS
+
+- 系统设置
+  - 用户管理
+  - 菜单管理
+  - 角色管理
+  - 国际化
+  - 操作日志
+
+- 关于
+```
+
+## 📷 系统截图
+
+<table>
+  <tr>
+    <td><img src="./web/src/assets/demo/1.jpg" alt="登录页面"></td>
+    <td><img src="./web/src/assets/demo/2.jpg" alt="首页仪表盘"></td>
+  </tr>
+  <tr>
+    <td><img src="./web/src/assets/demo/3.jpg" alt="消息公告"></td>
+    <td><img src="./web/src/assets/demo/4.png" alt="组织管理"></td>
+  </tr>
+  <tr>
+    <td><img src="./web/src/assets/demo/5.jpg" alt="岗位管理"></td>
+    <td><img src="./web/src/assets/demo/6.jpg" alt="组织架构"></td>
+  </tr>
+  <tr>
+    <td><img src="./web/src/assets/demo/7.jpg" alt="功能页-验证码"></td>
+    <td><img src="./web/src/assets/demo/8.jpg" alt="功能页-打印"></td>
+  </tr>
+  <tr>
+    <td><img src="./web/src/assets/demo/9.jpg" alt="功能页-拾色器"></td>
+    <td><img src="./web/src/assets/demo/10.jpg" alt="功能页-甘特图"></td>
+  </tr>
+  <tr>
+    <td><img src="./web/src/assets/demo/11.jpg" alt="系统设置-用户管理"></td>
+    <td><img src="./web/src/assets/demo/12.jpg" alt="系统设置-菜单管理"></td>
+  </tr>
+  <tr>
+    <td><img src="./web/src/assets/demo/13.jpg" alt="系统设置-角色管理"></td>
+    <td><img src="./web/src/assets/demo/14.jpg" alt="系统设置-国际化"></td>
+  </tr>
+  <tr>
+    <td><img src="./web/src/assets/demo/15.jpg" alt="系统设置-操作日志"></td>
+    <td><img src="./web/src/assets/demo/16.jpg" alt="关于页面"></td>
+  </tr>
+</table>
+
+## 📝 项目说明
+1. 本项目主要用于学习和技术交流,可能存在一些未经严格测试的功能点
+2. 仅供学习和个人非商业用途使用
+3. 欢迎通过 [Issues](https://github.com/baiwumm/vue3-admin/issues) 提交问题反馈
+4. 欢迎提交 [Pull Requests](https://github.com/baiwumm/vue3-admin/pulls) 参与项目改进
+
+## 🙏 特别鸣谢
+<div align="center">
+  <p><b>本项目 CDN 加速及安全防护由 Tencent EdgeOne 赞助</b></p>
+  <a href="https://edgeone.ai/zh?from=github" target="_blank">
+    <img width="300" src="./EdgeOne.png" alt="Tencent EdgeOne">
+  </a>
+  <p><a href="https://edgeone.ai/zh?from=github" target="_blank">亚洲最佳CDN、边缘和安全解决方案 - Tencent EdgeOne</a></p>
+</div>
+
+## 📄 许可证
+
+本项目基于 [MIT许可证](./LICENSE) 开源。
+
+## ⭐ Star 历史
+
+<div align="center">
+  
+  [![Star History Chart](https://api.star-history.com/svg?repos=baiwumm/vue3-admin&type=Date)](https://star-history.com/#baiwumm/vue3-admin&Date)
+  
+</div>

+ 291 - 0
deploy-2c2g.md

@@ -0,0 +1,291 @@
+# Vue3-Admin 2核2GB服务器部署指南
+
+本指南专门针对**2核2GB内存**的小配置服务器进行优化,确保项目能够稳定运行。
+
+## 📊 资源预算
+
+### 内存分配计划
+- **PostgreSQL**: 512MB (优化配置)
+- **Node.js应用**: 768MB (包含前后端)
+- **系统和Docker开销**: ~400MB
+- **缓冲区**: ~340MB
+
+**总计**: ~2GB (刚好合适)
+
+### CPU分配
+- **PostgreSQL**: 1.0核心
+- **Node.js应用**: 1.5核心
+
+## 🚀 快速部署
+
+### 1. 服务器优化(重要!)
+
+首先创建swap交换文件增加虚拟内存:
+
+```bash
+# 创建优化脚本
+cat > optimize-server.sh << 'EOF'
+#!/bin/bash
+echo "🔧 优化2GB服务器配置..."
+
+# 创建1GB swap文件
+if [ ! -f /swapfile ]; then
+    echo "创建1GB swap文件..."
+    sudo fallocate -l 1G /swapfile
+    sudo chmod 600 /swapfile
+    sudo mkswap /swapfile
+    sudo swapon /swapfile
+    echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
+fi
+
+# 优化内核参数
+echo "优化内核参数..."
+sudo tee /etc/sysctl.d/99-vue3-admin.conf << 'SYSCTL'
+# 内存优化
+vm.swappiness=10
+vm.vfs_cache_pressure=50
+vm.dirty_background_ratio=5
+vm.dirty_ratio=10
+
+# 网络优化  
+net.core.somaxconn=1024
+net.core.netdev_max_backlog=5000
+net.ipv4.tcp_max_syn_backlog=2048
+
+# 文件系统优化
+fs.file-max=65536
+SYSCTL
+
+sudo sysctl -p /etc/sysctl.d/99-vue3-admin.conf
+
+# 清理系统缓存
+echo "清理系统缓存..."
+sudo apt-get autoremove -y
+sudo apt-get autoclean
+sudo docker system prune -f
+
+echo "✅ 服务器优化完成!"
+EOF
+
+chmod +x optimize-server.sh
+./optimize-server.sh
+```
+
+### 2. 部署应用
+
+```bash
+# 复制环境变量
+cp env.example .env
+
+# 编辑配置(可选)
+nano .env
+
+# 使用低内存配置部署
+docker-compose -f docker-compose.low-memory.yml up -d
+
+# 等待启动完成
+sleep 60
+
+# 检查服务状态
+docker-compose -f docker-compose.low-memory.yml ps
+```
+
+## 📈 性能监控
+
+### 实时监控脚本
+
+创建监控脚本:
+
+```bash
+cat > monitor.sh << 'EOF'
+#!/bin/bash
+echo "========== 系统资源监控 =========="
+echo "时间: $(date)"
+echo ""
+
+echo "内存使用情况:"
+free -h
+
+echo ""
+echo "CPU使用情况:"
+top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1
+
+echo ""
+echo "Docker容器状态:"
+docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}"
+
+echo ""
+echo "磁盘使用情况:"
+df -h | grep -E "(/$|/var)"
+
+echo ""
+echo "Swap使用情况:"
+swapon --show
+
+echo "====================================="
+EOF
+
+chmod +x monitor.sh
+
+# 每30秒监控一次
+watch -n 30 ./monitor.sh
+```
+
+### 自动监控和告警
+
+```bash
+# 创建资源监控脚本
+cat > resource-check.sh << 'EOF'
+#!/bin/bash
+MEMORY_THRESHOLD=90
+CPU_THRESHOLD=90
+
+# 检查内存使用率
+MEMORY_USAGE=$(free | grep Mem | awk '{printf("%.0f", $3/$2 * 100.0)}')
+if [ $MEMORY_USAGE -gt $MEMORY_THRESHOLD ]; then
+    echo "⚠️  内存使用率过高: ${MEMORY_USAGE}%"
+    echo "重启应用服务..."
+    docker-compose -f docker-compose.low-memory.yml restart app
+fi
+
+# 检查CPU使用率
+CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1 | cut -d',' -f1)
+if (( $(echo "$CPU_USAGE > $CPU_THRESHOLD" | bc -l) )); then
+    echo "⚠️  CPU使用率过高: ${CPU_USAGE}%"
+fi
+
+# 检查Docker容器状态
+CONTAINER_STATUS=$(docker-compose -f docker-compose.low-memory.yml ps -q | wc -l)
+if [ $CONTAINER_STATUS -lt 2 ]; then
+    echo "⚠️  容器数量异常,尝试重启..."
+    docker-compose -f docker-compose.low-memory.yml up -d
+fi
+EOF
+
+chmod +x resource-check.sh
+
+# 添加到定时任务(每5分钟检查一次)
+(crontab -l 2>/dev/null; echo "*/5 * * * * $(pwd)/resource-check.sh >> $(pwd)/monitor.log 2>&1") | crontab -
+```
+
+## ⚡ 性能优化技巧
+
+### 1. 数据库优化
+
+```sql
+-- 连接数据库后执行这些优化查询
+-- docker-compose -f docker-compose.low-memory.yml exec postgres psql -U postgres -d vue3_admin
+
+-- 分析表统计信息
+ANALYZE;
+
+-- 重建索引
+REINDEX DATABASE vue3_admin;
+
+-- 清理无用数据
+VACUUM FULL;
+```
+
+### 2. 应用优化
+
+在 `server/src/main.ts` 中添加内存监控:
+
+```typescript
+// 内存监控(可选添加)
+setInterval(() => {
+  const memUsage = process.memoryUsage();
+  console.log(`内存使用: RSS ${Math.round(memUsage.rss / 1024 / 1024)}MB, Heap ${Math.round(memUsage.heapUsed / 1024 / 1024)}MB`);
+  
+  // 如果内存使用超过400MB,建议重启
+  if (memUsage.rss > 400 * 1024 * 1024) {
+    console.warn('⚠️  内存使用过高,建议重启应用');
+  }
+}, 60000); // 每分钟检查一次
+```
+
+### 3. 日志管理
+
+```bash
+# 创建日志清理脚本
+cat > cleanup-logs.sh << 'EOF'
+#!/bin/bash
+echo "清理Docker日志..."
+
+# 清理超过7天的容器日志
+docker system prune -f
+docker volume prune -f
+
+# 清理应用日志
+find ./server/upload -name "*.log" -mtime +7 -delete
+find /var/log -name "*.log.*" -mtime +7 -delete 2>/dev/null || true
+
+echo "日志清理完成"
+EOF
+
+chmod +x cleanup-logs.sh
+
+# 每天凌晨3点自动清理
+(crontab -l 2>/dev/null; echo "0 3 * * * $(pwd)/cleanup-logs.sh") | crontab -
+```
+
+## 🆘 紧急处理
+
+### 内存不足时的处理
+
+```bash
+# 1. 立即释放内存
+echo 3 | sudo tee /proc/sys/vm/drop_caches
+
+# 2. 重启应用(保持数据库运行)
+docker-compose -f docker-compose.low-memory.yml restart app
+
+# 3. 如果还是不够,重启所有服务
+docker-compose -f docker-compose.low-memory.yml restart
+
+# 4. 最后手段:清理Docker并重启
+docker system prune -af
+docker-compose -f docker-compose.low-memory.yml up -d
+```
+
+### 应用无响应时
+
+```bash
+# 检查进程
+docker-compose -f docker-compose.low-memory.yml top
+
+# 查看容器日志
+docker-compose -f docker-compose.low-memory.yml logs app --tail=50
+
+# 重启应用容器
+docker-compose -f docker-compose.low-memory.yml restart app
+```
+
+## 📋 部署检查清单
+
+- [ ] 服务器已创建swap文件
+- [ ] 内核参数已优化
+- [ ] Docker已安装并运行
+- [ ] 环境变量已配置
+- [ ] 使用低内存配置文件部署
+- [ ] 监控脚本已设置
+- [ ] 定时任务已添加
+- [ ] 应用可正常访问
+- [ ] 数据库连接正常
+
+## 🔍 常见问题
+
+**Q: 应用启动很慢?**
+A: 这是正常的,2GB内存启动需要60-90秒,请耐心等待。
+
+**Q: 偶尔出现502错误?**
+A: 可能是内存不足导致的,检查监控日志,必要时重启应用。
+
+**Q: 数据库连接失败?**
+A: 检查PostgreSQL容器是否正常运行,可能需要更多启动时间。
+
+**Q: 如何查看详细的资源使用?**
+A: 运行 `./monitor.sh` 脚本查看实时资源使用情况。
+
+---
+
+通过以上优化配置,你的2核2GB服务器应该可以稳定运行Vue3-Admin项目。如有问题,请查看监控日志进行排查。 

+ 99 - 0
docker-compose.low-memory.yml

@@ -0,0 +1,99 @@
+version: '3.8'
+
+services:
+  # PostgreSQL 数据库 - 低内存优化配置
+  postgres:
+    image: postgres:15-alpine
+    container_name: vue3-admin-postgres
+    restart: unless-stopped
+    environment:
+      POSTGRES_DB: vue3_admin
+      POSTGRES_USER: postgres
+      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-123456}
+      # 低内存优化配置
+      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
+    command: |
+      postgres
+      -c shared_buffers=64MB
+      -c effective_cache_size=256MB
+      -c maintenance_work_mem=32MB
+      -c checkpoint_completion_target=0.9
+      -c wal_buffers=4MB
+      -c default_statistics_target=100
+      -c random_page_cost=1.1
+      -c effective_io_concurrency=200
+      -c work_mem=2MB
+      -c min_wal_size=1GB
+      -c max_wal_size=2GB
+      -c max_connections=50
+    volumes:
+      - postgres_data:/var/lib/postgresql/data
+      - ./postgreSQL:/docker-entrypoint-initdb.d
+    ports:
+      - "5432:5432"
+    networks:
+      - vue3-admin-network
+    healthcheck:
+      test: ["CMD-SHELL", "pg_isready -U postgres"]
+      interval: 30s
+      timeout: 10s
+      retries: 3
+    # 资源限制
+    deploy:
+      resources:
+        limits:
+          memory: 512M
+          cpus: '1.0'
+        reservations:
+          memory: 256M
+          cpus: '0.3'
+
+  # 主应用服务 - 低内存优化配置
+  app:
+    build:
+      context: .
+      dockerfile: Dockerfile
+    container_name: vue3-admin-app
+    restart: unless-stopped
+    ports:
+      - "80:80"
+      - "6666:6666"
+    environment:
+      - NODE_ENV=production
+      - NODE_OPTIONS=--max-old-space-size=512
+      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD:-123456}@postgres:5432/vue3_admin
+      - JWT_SECRET=${JWT_SECRET:-your-jwt-secret-key-here}
+      - SESSION_SECRET=${SESSION_SECRET:-your-session-secret-key-here}
+    volumes:
+      - ./server/upload:/app/server/upload
+      - app_logs:/app/logs
+    depends_on:
+      postgres:
+        condition: service_healthy
+    networks:
+      - vue3-admin-network
+    healthcheck:
+      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:6666/health"]
+      interval: 45s
+      timeout: 15s
+      retries: 5
+      start_period: 60s
+    # 资源限制
+    deploy:
+      resources:
+        limits:
+          memory: 768M
+          cpus: '1.5'
+        reservations:
+          memory: 384M
+          cpus: '0.5'
+
+networks:
+  vue3-admin-network:
+    driver: bridge
+
+volumes:
+  postgres_data:
+    driver: local
+  app_logs:
+    driver: local 

+ 63 - 0
docker-compose.yml

@@ -0,0 +1,63 @@
+version: '3.8'
+
+services:
+  # PostgreSQL 数据库
+  postgres:
+    image: postgres:15-alpine
+    container_name: vue3-admin-postgres
+    restart: unless-stopped
+    environment:
+      POSTGRES_DB: vue3_admin
+      POSTGRES_USER: postgres
+      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-123456}
+    volumes:
+      - postgres_data:/var/lib/postgresql/data
+      - ./postgreSQL:/docker-entrypoint-initdb.d
+    ports:
+      - "5432:5432"
+    networks:
+      - vue3-admin-network
+    healthcheck:
+      test: ["CMD-SHELL", "pg_isready -U postgres"]
+      interval: 30s
+      timeout: 10s
+      retries: 3
+
+  # 主应用服务(前端 + 后端)
+  app:
+    build:
+      context: .
+      dockerfile: Dockerfile
+    container_name: vue3-admin-app
+    restart: unless-stopped
+    ports:
+      - "80:80"
+      - "6666:6666"
+    environment:
+      - NODE_ENV=production
+      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD:-123456}@postgres:5432/vue3_admin
+      - JWT_SECRET=${JWT_SECRET:-your-jwt-secret-key-here}
+      - SESSION_SECRET=${SESSION_SECRET:-your-session-secret-key-here}
+    volumes:
+      - ./server/upload:/app/server/upload
+      - app_logs:/app/logs
+    depends_on:
+      postgres:
+        condition: service_healthy
+    networks:
+      - vue3-admin-network
+    healthcheck:
+      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:6666/health"]
+      interval: 30s
+      timeout: 10s
+      retries: 3
+
+networks:
+  vue3-admin-network:
+    driver: bridge
+
+volumes:
+  postgres_data:
+    driver: local
+  app_logs:
+    driver: local 

+ 233 - 0
docker-deploy.md

@@ -0,0 +1,233 @@
+# Vue3-Admin Docker 部署指南
+
+本项目提供了完整的 Docker 化部署方案,包含前端(Vue3)、后端(NestJS)和数据库(PostgreSQL)服务。
+
+## 🚀 快速开始
+
+### 1. 环境准备
+
+确保你的系统已安装:
+- Docker (>= 20.0.0)
+- Docker Compose (>= 2.0.0)
+
+### 2. 环境配置
+
+复制环境变量模板并配置:
+
+```bash
+# 复制环境变量模板
+cp env.example .env
+
+# 编辑环境变量(可选)
+vi .env
+```
+
+主要配置项:
+- `POSTGRES_PASSWORD`: PostgreSQL 数据库密码
+- `DATABASE_URL`: 数据库连接字符串
+- `JWT_SECRET`: JWT 加密密钥
+- `SESSION_SECRET`: Session 会话密钥
+
+### 3. 部署应用
+
+```bash
+# 构建并启动所有服务
+docker-compose up -d
+
+# 查看服务状态
+docker-compose ps
+
+# 查看日志
+docker-compose logs -f app
+```
+
+### 4. 访问应用
+
+- **前端应用**: http://localhost
+- **后端API**: http://localhost:6666
+- **Swagger文档**: http://localhost/docs
+- **数据库**: localhost:5432
+
+## 📁 项目结构
+
+```
+vue3-admin/
+├── Dockerfile              # 多阶段构建文件
+├── docker-compose.yml      # 服务编排文件
+├── nginx.conf              # Nginx 配置
+├── .dockerignore           # Docker 忽略文件
+├── env.example             # 环境变量模板
+├── server/                 # 后端代码
+└── web/                    # 前端代码
+```
+
+## 🛠️ 服务说明
+
+### 应用服务 (app)
+- **端口**: 80 (Nginx), 6666 (API)
+- **功能**: 前端静态文件服务 + 后端API服务
+- **健康检查**: http://localhost:6666/health
+
+### 数据库服务 (postgres)
+- **镜像**: postgres:15-alpine
+- **端口**: 5432
+- **数据卷**: postgres_data
+- **初始化**: 自动执行 postgreSQL/ 目录下的 SQL 文件
+
+## 🔧 常用命令
+
+### 服务管理
+
+```bash
+# 启动服务
+docker-compose up -d
+
+# 停止服务
+docker-compose down
+
+# 重启服务
+docker-compose restart
+
+# 重新构建
+docker-compose build --no-cache
+
+# 查看状态
+docker-compose ps
+
+# 查看日志
+docker-compose logs -f [service_name]
+```
+
+### 数据库管理
+
+```bash
+# 进入数据库容器
+docker-compose exec postgres psql -U postgres -d vue3_admin
+
+# 数据库备份
+docker-compose exec postgres pg_dump -U postgres vue3_admin > backup.sql
+
+# 数据库恢复
+docker-compose exec -T postgres psql -U postgres vue3_admin < backup.sql
+```
+
+### 应用管理
+
+```bash
+# 进入应用容器
+docker-compose exec app sh
+
+# 查看应用日志
+docker-compose logs -f app
+
+# 重启应用服务
+docker-compose restart app
+```
+
+## 🐛 故障排除
+
+### 常见问题
+
+1. **端口冲突**
+   ```bash
+   # 修改 docker-compose.yml 中的端口映射
+   ports:
+     - "8080:80"    # 前端改为8080端口
+     - "3000:6666"  # 后端改为3000端口
+   ```
+
+2. **数据库连接失败**
+   ```bash
+   # 检查数据库服务状态
+   docker-compose logs postgres
+   
+   # 检查环境变量配置
+   docker-compose config
+   ```
+
+3. **前端页面无法访问**
+   ```bash
+   # 检查Nginx配置
+   docker-compose exec app nginx -t
+   
+   # 重启Nginx
+   docker-compose exec app nginx -s reload
+   ```
+
+4. **构建失败**
+   ```bash
+   # 清理Docker缓存
+   docker system prune -a
+   
+   # 重新构建
+   docker-compose build --no-cache
+   ```
+
+### 查看详细日志
+
+```bash
+# 查看所有服务日志
+docker-compose logs
+
+# 查看特定服务日志
+docker-compose logs app
+docker-compose logs postgres
+
+# 实时跟踪日志
+docker-compose logs -f --tail=100 app
+```
+
+## 📊 监控和维护
+
+### 健康检查
+
+所有服务都配置了健康检查:
+
+```bash
+# 检查服务健康状态
+docker-compose ps
+
+# 应用健康检查
+curl http://localhost:6666/health
+
+# 数据库健康检查
+docker-compose exec postgres pg_isready -U postgres
+```
+
+### 数据持久化
+
+项目使用 Docker 卷持久化数据:
+
+- `postgres_data`: PostgreSQL 数据
+- `app_logs`: 应用日志
+- `./server/upload`: 上传文件
+
+## 🔒 生产环境建议
+
+1. **安全配置**
+   - 修改默认密码
+   - 使用强密码策略
+   - 配置防火墙规则
+   - 启用 HTTPS
+
+2. **性能优化**
+   - 调整数据库配置
+   - 设置Nginx缓存策略
+   - 优化Node.js内存使用
+   - 监控资源使用情况
+
+3. **备份策略**
+   - 定期备份数据库
+   - 备份上传文件
+   - 配置日志轮转
+
+4. **监控告警**
+   - 配置应用监控
+   - 设置资源告警
+   - 日志监控
+
+## 📝 更新日志
+
+- v1.0.0: 初始版本,支持基础Docker部署
+- 支持的服务:Vue3前端、NestJS后端、PostgreSQL
+- 自动化部署和健康检查 

+ 68 - 0
env.example

@@ -0,0 +1,68 @@
+# ===================================
+# 数据库配置
+# ===================================
+# PostgreSQL 数据库连接字符串
+DATABASE_URL="postgresql://postgres:123456@localhost:5432/vue3_admin"
+
+# PostgreSQL 数据库密码(用于Docker部署)
+POSTGRES_PASSWORD=123456
+
+# ===================================
+# 应用配置
+# ===================================
+# 应用运行环境
+NODE_ENV=production
+
+# JWT密钥
+JWT_SECRET=your-jwt-secret-key-here
+
+# Session密钥
+SESSION_SECRET=your-session-secret-key-here
+
+# ===================================
+# 服务端口配置
+# ===================================
+# 后端API服务端口
+API_PORT=6666
+
+# 前端服务端口(Nginx)
+WEB_PORT=80
+
+# ===================================
+# 文件上传配置
+# ===================================
+# 上传文件存储路径
+UPLOAD_PATH=./server/upload
+
+# 最大文件上传大小(MB)
+MAX_FILE_SIZE=100
+
+# ===================================
+# 日志配置
+# ===================================
+# 日志级别 (error, warn, info, debug)
+LOG_LEVEL=info
+
+# 日志文件路径
+LOG_PATH=./logs
+
+# ===================================
+# 邮件配置(可选)
+# ===================================
+# SMTP服务器配置
+SMTP_HOST=smtp.example.com
+SMTP_PORT=587
+SMTP_USER=your-email@example.com
+SMTP_PASS=your-email-password
+
+# ===================================
+# 其他配置
+# ===================================
+# API基础URL
+API_BASE_URL=http://localhost:6666/api
+
+# 前端基础URL
+WEB_BASE_URL=http://localhost
+
+# 是否启用Swagger文档
+ENABLE_SWAGGER=true 

+ 134 - 0
nginx.conf

@@ -0,0 +1,134 @@
+user nginx;
+worker_processes auto;
+error_log /var/log/nginx/error.log warn;
+pid /var/run/nginx.pid;
+
+events {
+    worker_connections 1024;
+    use epoll;
+    multi_accept on;
+}
+
+http {
+    include /etc/nginx/mime.types;
+    default_type application/octet-stream;
+
+    # 日志格式
+    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+                    '$status $body_bytes_sent "$http_referer" '
+                    '"$http_user_agent" "$http_x_forwarded_for"';
+
+    access_log /var/log/nginx/access.log main;
+
+    # 基本配置
+    sendfile on;
+    tcp_nopush on;
+    tcp_nodelay on;
+    keepalive_timeout 65;
+    types_hash_max_size 2048;
+    client_max_body_size 100m;
+
+    # Gzip 压缩
+    gzip on;
+    gzip_vary on;
+    gzip_proxied any;
+    gzip_comp_level 6;
+    gzip_types
+        text/plain
+        text/css
+        text/xml
+        text/javascript
+        application/json
+        application/javascript
+        application/xml+rss
+        application/atom+xml
+        image/svg+xml;
+
+    # 上游后端服务器
+    upstream backend {
+        server localhost:6666;
+    }
+
+    server {
+        listen 80;
+        server_name localhost;
+        root /app/web/dist;
+        index index.html;
+
+        # 静态资源缓存
+        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
+            expires 1y;
+            add_header Cache-Control "public, immutable";
+            add_header Access-Control-Allow-Origin "*";
+        }
+
+        # API 代理到后端
+        location /api {
+            proxy_pass http://backend;
+            proxy_http_version 1.1;
+            proxy_set_header Upgrade $http_upgrade;
+            proxy_set_header Connection 'upgrade';
+            proxy_set_header Host $host;
+            proxy_set_header X-Real-IP $remote_addr;
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+            proxy_set_header X-Forwarded-Proto $scheme;
+            proxy_cache_bypass $http_upgrade;
+            proxy_connect_timeout 30s;
+            proxy_send_timeout 30s;
+            proxy_read_timeout 30s;
+        }
+
+        # Swagger 文档代理
+        location /docs {
+            proxy_pass http://backend;
+            proxy_http_version 1.1;
+            proxy_set_header Upgrade $http_upgrade;
+            proxy_set_header Connection 'upgrade';
+            proxy_set_header Host $host;
+            proxy_set_header X-Real-IP $remote_addr;
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+            proxy_set_header X-Forwarded-Proto $scheme;
+            proxy_cache_bypass $http_upgrade;
+        }
+
+        # 静态文件代理(上传的文件)
+        location /static {
+            proxy_pass http://backend;
+            proxy_http_version 1.1;
+            proxy_set_header Host $host;
+            proxy_set_header X-Real-IP $remote_addr;
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+            proxy_set_header X-Forwarded-Proto $scheme;
+        }
+
+        # 健康检查
+        location /health {
+            proxy_pass http://backend;
+            proxy_http_version 1.1;
+            proxy_set_header Host $host;
+            proxy_set_header X-Real-IP $remote_addr;
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+            proxy_set_header X-Forwarded-Proto $scheme;
+        }
+
+        # Vue Router 历史模式支持
+        location / {
+            try_files $uri $uri/ /index.html;
+            add_header Cache-Control "no-store, no-cache, must-revalidate";
+        }
+
+        # 安全头
+        add_header X-Frame-Options "SAMEORIGIN" always;
+        add_header X-XSS-Protection "1; mode=block" always;
+        add_header X-Content-Type-Options "nosniff" always;
+        add_header Referrer-Policy "no-referrer-when-downgrade" always;
+        add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
+
+        # 错误页面
+        error_page 404 /index.html;
+        error_page 500 502 503 504 /50x.html;
+        location = /50x.html {
+            root /usr/share/nginx/html;
+        }
+    }
+} 

+ 478 - 0
postgreSQL/Internalization.sql

@@ -0,0 +1,478 @@
+/*
+ Navicat Premium Dump SQL
+
+ Source Server         : postgreSQL
+ Source Server Type    : PostgreSQL
+ Source Server Version : 160003 (160003)
+ Source Host           : localhost:5432
+ Source Catalog        : vue3-admin
+ Source Schema         : public
+
+ Target Server Type    : PostgreSQL
+ Target Server Version : 160003 (160003)
+ File Encoding         : 65001
+
+ Date: 31/10/2024 10:16:30
+*/
+
+
+-- ----------------------------
+-- Table structure for Internalization
+-- ----------------------------
+DROP TABLE IF EXISTS "public"."Internalization";
+CREATE TABLE "public"."Internalization" (
+  "id" text COLLATE "pg_catalog"."default" NOT NULL,
+  "name" text COLLATE "pg_catalog"."default" NOT NULL,
+  "parentId" text COLLATE "pg_catalog"."default",
+  "zhCN" text COLLATE "pg_catalog"."default",
+  "enUS" text COLLATE "pg_catalog"."default",
+  "jaJP" text COLLATE "pg_catalog"."default",
+  "zhTW" text COLLATE "pg_catalog"."default",
+  "createdAt" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  "updatedAt" timestamp(3) NOT NULL
+)
+;
+
+-- ----------------------------
+-- Records of Internalization
+-- ----------------------------
+INSERT INTO "public"."Internalization" VALUES ('54d1a5bd-0275-4a27-a613-63f679a50d4d', 'system', NULL, NULL, NULL, NULL, NULL, '2024-08-15 02:56:57.912', '2024-08-15 02:56:57.912');
+INSERT INTO "public"."Internalization" VALUES ('9ec5117e-370f-4785-8ea4-42fc72399be2', 'updateTitle', '54d1a5bd-0275-4a27-a613-63f679a50d4d', '系统版本更新通知', 'System version update notification', 'システム更新のお知らせです', '系統版本更新通知', '2024-08-15 02:59:31.025', '2024-08-15 02:59:31.025');
+INSERT INTO "public"."Internalization" VALUES ('40ff1dc0-cd84-4e66-9d8f-cff1730edf73', 'updateContent', '54d1a5bd-0275-4a27-a613-63f679a50d4d', '检测到系统有新版本发布,是否立即刷新页面?', 'A new version of the system has been detected. Do you want to refresh the page immediately?', 'システムの新しいバージョンのリリースを検出して、すぐにページを更新しますか?', '檢測到系統有新版本發布,是否立即刷新頁面?', '2024-08-15 08:23:28.838', '2024-08-15 08:23:28.838');
+INSERT INTO "public"."Internalization" VALUES ('fb21e33f-72ee-4da5-8bb0-db9834ed138a', 'updateConfirm', '54d1a5bd-0275-4a27-a613-63f679a50d4d', '立即刷新', 'Refresh immediately', 'すぐにリフレッシュします', '立即刷新', '2024-08-15 08:24:19.95', '2024-08-15 08:24:19.95');
+INSERT INTO "public"."Internalization" VALUES ('e4393e17-9a44-4712-9902-b32c743c8653', 'updateCancel', '54d1a5bd-0275-4a27-a613-63f679a50d4d', '稍后再说', 'Later', 'あとでお話しします', '稍後再說', '2024-08-15 08:25:12.941', '2024-08-15 08:25:12.941');
+INSERT INTO "public"."Internalization" VALUES ('5892893b-70fb-4e2d-9ea8-0793bc48fd5d', 'common', NULL, NULL, NULL, NULL, NULL, '2024-08-15 08:25:45.581', '2024-08-15 08:25:45.581');
+INSERT INTO "public"."Internalization" VALUES ('97e2e8f8-f1fa-46c6-a7b6-36ea514c242d', 'add', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '新增', 'Add', '新たに増えます', '新增', '2024-08-15 08:26:12.151', '2024-08-15 08:26:12.151');
+INSERT INTO "public"."Internalization" VALUES ('5bd032a5-0549-42e4-98da-582a2a84f7d7', 'addSuccess', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '添加成功', 'Add Success', '追加成功です', '添加成功', '2024-08-15 08:26:53.106', '2024-08-15 08:26:53.106');
+INSERT INTO "public"."Internalization" VALUES ('2e64da04-cc7e-436d-893e-5681fe3eb90d', 'backToHome', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '返回首页', 'Back to home', 'トップページに戻ります', '返回首頁', '2024-08-15 08:27:31.511', '2024-08-15 08:27:31.511');
+INSERT INTO "public"."Internalization" VALUES ('777d592c-7ba8-4af8-b851-3bfc3fb468d1', 'batchDelete', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '批量删除', 'Batch Delete', '一括削除です', '批量刪除', '2024-08-15 08:28:08.445', '2024-08-15 08:28:08.445');
+INSERT INTO "public"."Internalization" VALUES ('9fdf2477-4391-4be5-a6b8-4c2a6f255aab', 'cancel', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '取消', 'Cancel', '取り消します', '取消', '2024-08-15 08:28:47.194', '2024-08-15 08:28:47.194');
+INSERT INTO "public"."Internalization" VALUES ('b7c5c261-dea3-4638-a8e3-0a85abc10e50', 'columnSetting', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '列设置', 'Column Setting', '列設定です', '列設置', '2024-08-15 08:29:36.064', '2024-08-15 08:29:36.064');
+INSERT INTO "public"."Internalization" VALUES ('bb0f1bf9-5042-4646-8974-9b40adf1bffd', 'confirm', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '确认', 'Confirm', '確認します', '確認', '2024-08-15 08:30:20.524', '2024-08-15 08:30:20.524');
+INSERT INTO "public"."Internalization" VALUES ('99acf799-cab2-47bd-9cef-6a427acec5cb', 'delete', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '删除', 'Delete', '削除します', '刪除', '2024-08-15 08:30:59.717', '2024-08-15 08:30:59.717');
+INSERT INTO "public"."Internalization" VALUES ('7b75fd61-dc5c-4f81-bc8e-e7ccb57a8b3d', 'deleteSuccess', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '删除成功', 'Delete Success', '削除成功です', '刪除成功', '2024-08-15 08:31:41.947', '2024-08-15 08:31:41.947');
+INSERT INTO "public"."Internalization" VALUES ('b1a1e382-d5db-4eff-bb80-8fcc7f08ac13', 'confirmDelete', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '确认删除吗?', 'Are you sure you want to delete?', '削除を確認しますか?', '確認刪除嗎?', '2024-08-15 08:32:23.633', '2024-08-15 08:32:23.633');
+INSERT INTO "public"."Internalization" VALUES ('99ff60a8-f491-456d-853e-b60b310e5427', 'edit', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '编辑', 'Edit', '編集します', '編輯', '2024-08-15 08:33:16.522', '2024-08-15 08:33:16.522');
+INSERT INTO "public"."Internalization" VALUES ('52c83ddc-6205-4027-be1c-8d4326d017bd', 'error', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '错误', 'Error', '間違いです', '錯誤', '2024-08-15 08:33:59.433', '2024-08-15 08:33:59.433');
+INSERT INTO "public"."Internalization" VALUES ('3b9443ef-37c0-4a72-9aba-cb59a0bfae96', 'logout', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '退出登录', 'Logout', 'ログアウトします', '退出登錄', '2024-08-15 08:35:13.697', '2024-08-15 08:35:13.697');
+INSERT INTO "public"."Internalization" VALUES ('2fd0bb79-6a0c-4efe-b182-882194c99b71', 'logoutConfirm', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '确认退出登录吗?', 'Are you sure you want to log out?', 'ログアウトを確認しますか?', '確認退出登錄嗎?', '2024-08-15 08:36:03.425', '2024-08-15 08:36:03.425');
+INSERT INTO "public"."Internalization" VALUES ('a8132ac9-0b47-4f23-b876-304d1d4de1e2', 'lookForward', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '敬请期待', 'Coming soon', 'ご期待願います', '敬請期待', '2024-08-15 08:36:52.161', '2024-08-15 08:36:52.161');
+INSERT INTO "public"."Internalization" VALUES ('4ffa7e48-ae3c-4ab2-ae9a-bc929a34371d', 'operate', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '操作', 'Operate', '操作します', '操作', '2024-08-15 08:37:46.88', '2024-08-15 08:37:46.88');
+INSERT INTO "public"."Internalization" VALUES ('202eb8f7-995c-4da1-b19a-976742f6a230', 'refresh', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '刷新', 'Refresh', 'リフレッシュします', '刷新', '2024-08-15 08:38:24.112', '2024-08-15 08:38:24.112');
+INSERT INTO "public"."Internalization" VALUES ('d160ca68-2f5d-4880-931e-e9fce5b8376e', 'reset', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '重置', 'Reset', 'リセットします', '重置', '2024-08-15 08:38:57.232', '2024-08-15 08:38:57.232');
+INSERT INTO "public"."Internalization" VALUES ('97233eda-292e-4c0c-a4fe-d82064078e10', 'search', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '搜索', 'Search', '検索します', '搜索', '2024-08-15 08:39:25.191', '2024-08-15 08:39:25.191');
+INSERT INTO "public"."Internalization" VALUES ('89237e03-fffb-4a98-83a7-1b1e5557c354', 'tip', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '提示', 'Tip', 'ヒントです', '提示', '2024-08-15 08:39:57.519', '2024-08-15 08:39:57.519');
+INSERT INTO "public"."Internalization" VALUES ('31fe3378-6cb0-4890-ab89-8fc3d3844f49', 'userCenter', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '个人中心', 'User Center', '個人センターです', '個人中心', '2024-08-15 08:41:59.384', '2024-08-15 08:41:59.384');
+INSERT INTO "public"."Internalization" VALUES ('2320ff06-aff4-4503-b168-9c2e6eda85a5', 'createdAt', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '创建时间', 'CreatedAt', '作成時間です', '創建時間', '2024-08-15 08:43:13.039', '2024-08-15 08:43:13.039');
+INSERT INTO "public"."Internalization" VALUES ('07ab6ae9-8309-431b-b9ce-d78b051b6785', 'updatedAt', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '更新时间', 'UpdatedAt', '更新時間です', '更新時間', '2024-08-15 08:43:47.375', '2024-08-15 08:43:47.375');
+INSERT INTO "public"."Internalization" VALUES ('94adce17-b1ae-4ae2-b897-a165772dc23c', 'prevStep', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '上一步', 'Previous', '一歩進みます', '上壹步', '2024-08-15 08:44:17.974', '2024-08-15 08:44:17.974');
+INSERT INTO "public"."Internalization" VALUES ('a1f86225-4378-43bd-80fa-a84ab6f0a54c', 'nextStep', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '下一步', 'Next', '次のステップです', '下壹步', '2024-08-15 08:44:48.382', '2024-08-15 08:44:48.382');
+INSERT INTO "public"."Internalization" VALUES ('398b51cd-6e9c-4994-8b3c-dd188ed730aa', 'commit', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '提交', 'Commit', '提出します', '提交', '2024-08-15 08:45:23.429', '2024-08-15 08:45:23.429');
+INSERT INTO "public"."Internalization" VALUES ('87f643e2-de02-41b2-bc4b-867273fe0295', 'route', NULL, NULL, NULL, NULL, NULL, '2024-08-15 08:48:04.43', '2024-08-15 08:48:04.43');
+INSERT INTO "public"."Internalization" VALUES ('65431db0-0f04-4b38-8220-c3fcbad518b4', 'login', '87f643e2-de02-41b2-bc4b-867273fe0295', '登录', 'Login', '登録します', '登錄', '2024-08-15 08:48:32.72', '2024-08-15 08:48:32.72');
+INSERT INTO "public"."Internalization" VALUES ('b0352a43-05c1-4159-b1d8-53a128e01b5b', '403', '87f643e2-de02-41b2-bc4b-867273fe0295', '无权限', 'No Permission', '権限がありません', '無權限', '2024-08-15 08:49:26.209', '2024-08-15 08:49:26.209');
+INSERT INTO "public"."Internalization" VALUES ('e2548567-f3ca-4a95-adce-eb5c775f90c5', '404', '87f643e2-de02-41b2-bc4b-867273fe0295', '页面不存在', 'Page Not Found', 'ページは存在しません', '頁面不存在', '2024-08-15 08:49:59.537', '2024-08-15 08:49:59.537');
+INSERT INTO "public"."Internalization" VALUES ('bdb1923f-b392-4764-a774-e8c1cffb9dd2', '500', '87f643e2-de02-41b2-bc4b-867273fe0295', '服务器错误', 'Server Error', 'サーバーエラーです', '服務器錯誤', '2024-08-15 08:50:35.185', '2024-08-15 08:50:35.185');
+INSERT INTO "public"."Internalization" VALUES ('19deb064-045b-46a9-94bb-ba20424d28b1', 'home', '87f643e2-de02-41b2-bc4b-867273fe0295', '首页', 'Home', 'トップページです', '首頁', '2024-08-15 08:51:06.942', '2024-08-15 08:51:06.942');
+INSERT INTO "public"."Internalization" VALUES ('76f695a8-f10f-4e6a-a326-e127a26d9691', 'user-center', '87f643e2-de02-41b2-bc4b-867273fe0295', '个人中心', 'User Center', '個人センターです', '個人中心', '2024-08-15 08:52:29.638', '2024-08-15 08:52:29.638');
+INSERT INTO "public"."Internalization" VALUES ('3f1ee5d1-12d7-47ad-9b6c-29744bea947f', 'about', '87f643e2-de02-41b2-bc4b-867273fe0295', '关于', 'About', 'についてです', '關于', '2024-08-15 08:53:34.823', '2024-08-15 08:53:34.823');
+INSERT INTO "public"."Internalization" VALUES ('b419c0ac-b93d-45e1-b5df-f0a672ab40af', 'sider', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', NULL, NULL, NULL, NULL, '2024-08-16 06:41:34.468', '2024-08-16 06:41:34.468');
+INSERT INTO "public"."Internalization" VALUES ('4e73b14d-e72b-415d-9ae1-a71359650c96', 'editSuccess', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', '更新成功', 'Update Success', '更新成功です', '更新成功', '2024-08-15 08:41:19.298', '2024-08-21 06:36:42.115');
+INSERT INTO "public"."Internalization" VALUES ('3a8ac8b6-7732-40db-8bfc-e52306b199e6', 'administrative', '87f643e2-de02-41b2-bc4b-867273fe0295', '智能行政', 'Administrative', 'スマート行政です', '智能行政', '2024-08-15 08:54:14.443', '2024-08-15 08:54:14.443');
+INSERT INTO "public"."Internalization" VALUES ('69f57651-85c7-4541-b077-416978ee7358', 'administrative_organization', '87f643e2-de02-41b2-bc4b-867273fe0295', '组织管理', 'Organization', '組織マネジメントです', '組織管理', '2024-08-15 08:54:49.764', '2024-08-15 08:54:49.764');
+INSERT INTO "public"."Internalization" VALUES ('5f0fc92f-4bef-464e-93d7-8a4227511460', 'administrative_post-manage', '87f643e2-de02-41b2-bc4b-867273fe0295', '岗位管理', 'Post Manage', '持ち場管理です', '崗位管理', '2024-08-15 08:55:22.86', '2024-08-15 08:55:22.86');
+INSERT INTO "public"."Internalization" VALUES ('ef777b2f-278a-4acd-9046-8670c911c8e2', 'system-manage', '87f643e2-de02-41b2-bc4b-867273fe0295', '系统管理', 'System Manage', 'システム管理です', '系統管理', '2024-08-15 08:55:54.134', '2024-08-15 08:55:54.134');
+INSERT INTO "public"."Internalization" VALUES ('c8a7a095-1dd8-4d0d-bc94-9027312ef718', 'system-manage_user-manage', '87f643e2-de02-41b2-bc4b-867273fe0295', '用户管理', 'User Manage', 'ユーザー管理です', '用戶管理', '2024-08-15 08:56:28.512', '2024-08-15 08:56:28.512');
+INSERT INTO "public"."Internalization" VALUES ('2bc63729-c827-4995-a292-be185531618a', 'system-manage_internalization', '87f643e2-de02-41b2-bc4b-867273fe0295', '国际化', 'Internalization', '国際化です', '國際化', '2024-08-15 08:57:13.73', '2024-08-15 08:57:13.73');
+INSERT INTO "public"."Internalization" VALUES ('995f6831-5de1-4c0b-bf1f-53b08c36ba6e', 'system-manage_operation-log', '87f643e2-de02-41b2-bc4b-867273fe0295', '操作日志', 'Operation Log', '操作履歴です', '操作日志', '2024-08-15 08:57:44.363', '2024-08-15 08:57:44.363');
+INSERT INTO "public"."Internalization" VALUES ('f3884914-186c-4e1c-9cb1-a6628383f0ef', 'theme', NULL, NULL, NULL, NULL, NULL, '2024-08-15 08:58:12.081', '2024-08-15 08:58:12.081');
+INSERT INTO "public"."Internalization" VALUES ('c42e9938-fa8b-4f86-849e-821b43a63a24', 'themeSchema', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', NULL, NULL, NULL, NULL, '2024-08-15 08:58:18.708', '2024-08-15 08:58:18.708');
+INSERT INTO "public"."Internalization" VALUES ('565fcb10-ef98-4482-bfca-fc823c062ff6', 'title', 'c42e9938-fa8b-4f86-849e-821b43a63a24', '主题模式', 'Theme Schema', 'テーマモードです', '主題模式', '2024-08-15 09:16:16.281', '2024-08-15 09:16:16.281');
+INSERT INTO "public"."Internalization" VALUES ('8257f5d5-cf88-402e-a43a-93795c531de9', 'light', 'c42e9938-fa8b-4f86-849e-821b43a63a24', '亮色模式', 'Light', '明るいパターンです', '亮色模式', '2024-08-15 09:16:52.747', '2024-08-15 09:16:52.747');
+INSERT INTO "public"."Internalization" VALUES ('87d062a9-233c-4b8e-ac04-5878aafbcf7b', 'dark', 'c42e9938-fa8b-4f86-849e-821b43a63a24', '暗黑模式', 'Dark', 'ダークモードです', '暗黑模式', '2024-08-15 09:18:26.227', '2024-08-15 09:18:26.227');
+INSERT INTO "public"."Internalization" VALUES ('fa3f83e0-60a5-4a5f-87f8-498f6a56e265', 'auto', 'c42e9938-fa8b-4f86-849e-821b43a63a24', '跟随系统', 'Follow System', 'システムに追従します', '跟隨系統', '2024-08-15 09:19:54.86', '2024-08-15 09:19:54.86');
+INSERT INTO "public"."Internalization" VALUES ('e367d9b8-290f-464c-a5e9-a31d9c755ed2', 'grayscale', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', '灰色模式', 'Grayscale', 'グレーパターンです', '灰色模式', '2024-08-15 09:20:27.946', '2024-08-15 09:20:27.946');
+INSERT INTO "public"."Internalization" VALUES ('f96c5652-d742-418f-8003-8e316dc03d46', 'layoutMode', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', NULL, NULL, NULL, NULL, '2024-08-15 09:20:42.647', '2024-08-15 09:20:42.647');
+INSERT INTO "public"."Internalization" VALUES ('b4955473-00bc-4c5a-9679-157bdc9fb953', 'title', 'f96c5652-d742-418f-8003-8e316dc03d46', '布局模式', 'Layout Mode', 'レイアウトパターンです', '布局模式', '2024-08-15 09:21:14.945', '2024-08-15 09:21:14.945');
+INSERT INTO "public"."Internalization" VALUES ('894b83fb-8fc9-4700-a864-7830a43aa564', 'vertical', 'f96c5652-d742-418f-8003-8e316dc03d46', '左侧菜单模式', 'Vertical Menu Mode', '左側メニューモードです', '左側菜單模式', '2024-08-15 09:21:51.376', '2024-08-15 09:21:51.376');
+INSERT INTO "public"."Internalization" VALUES ('fe0d1859-64f4-41af-ab96-b30a43da1c6c', 'horizontal', 'f96c5652-d742-418f-8003-8e316dc03d46', '顶部菜单模式', 'Horizontal Menu Mode', 'トップメニューモードです', '頂部菜單模式', '2024-08-15 09:22:27.392', '2024-08-15 09:22:27.392');
+INSERT INTO "public"."Internalization" VALUES ('3c24159a-6274-41cf-822f-b6ccd3e2e145', 'vertical-mix', 'f96c5652-d742-418f-8003-8e316dc03d46', '左侧菜单混合模式', 'Vertical Mix Menu Mode', '左側メニューミックスモードです', '左側菜單混合模式', '2024-08-15 09:23:07.062', '2024-08-15 09:23:07.062');
+INSERT INTO "public"."Internalization" VALUES ('fe6b4c3a-72e7-4fd1-8215-96e3e070496f', 'horizontal-mix', 'f96c5652-d742-418f-8003-8e316dc03d46', '顶部菜单混合模式', 'Horizontal Mix menu Mode', 'トップメニュー混合モードです', '頂部菜單混合模式', '2024-08-15 09:23:37.248', '2024-08-15 09:23:37.248');
+INSERT INTO "public"."Internalization" VALUES ('f4192322-ebde-44ef-a8a2-7d1aaa3a2d19', 'recommendColor', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', '应用推荐算法的颜色', 'Apply Recommended Color Algorithm', '推奨アルゴリズムの色を適用します', '應用推薦算法的顔色', '2024-08-15 09:24:18.281', '2024-08-15 09:24:18.281');
+INSERT INTO "public"."Internalization" VALUES ('673524d5-00a7-45ae-a935-4f2d796b1c5a', 'recommendColorDesc', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', '推荐颜色的算法参照', 'The recommended color algorithm refers to', '推奨色のアルゴリズムを参照します', '推薦顔色的算法參照', '2024-08-15 09:24:53.744', '2024-08-15 09:24:53.744');
+INSERT INTO "public"."Internalization" VALUES ('f3bd1511-1cb7-45c1-8c3b-ec7b00013126', 'themeColor', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', NULL, NULL, NULL, NULL, '2024-08-15 09:25:15.626', '2024-08-15 09:25:15.626');
+INSERT INTO "public"."Internalization" VALUES ('097a28d0-6175-4e05-b56d-3756f157259d', 'title', 'f3bd1511-1cb7-45c1-8c3b-ec7b00013126', '主题颜色', 'Theme Color', 'テーマカラーです', '主題顔色', '2024-08-15 09:25:47.244', '2024-08-15 09:25:47.244');
+INSERT INTO "public"."Internalization" VALUES ('7df09be9-e531-42b0-bf67-8496ec10de49', 'primary', 'f3bd1511-1cb7-45c1-8c3b-ec7b00013126', '主色', 'Primary', 'メインカラーです', '主色', '2024-08-15 09:26:20.061', '2024-08-15 09:26:20.061');
+INSERT INTO "public"."Internalization" VALUES ('4b23e6b5-c9e8-4174-8d1a-8f37668020e9', 'info', 'f3bd1511-1cb7-45c1-8c3b-ec7b00013126', '信息色', 'Info', '情報色です', '信息色', '2024-08-15 09:26:48.969', '2024-08-15 09:26:48.969');
+INSERT INTO "public"."Internalization" VALUES ('0e2dee3d-99d3-42c6-824f-015600dbb255', 'success', 'f3bd1511-1cb7-45c1-8c3b-ec7b00013126', '成功色', 'Success', '成功色です', '成功色', '2024-08-15 09:27:14.279', '2024-08-15 09:27:14.279');
+INSERT INTO "public"."Internalization" VALUES ('1397b4d3-cad4-45ce-a708-75f3a419d23c', 'warning', 'f3bd1511-1cb7-45c1-8c3b-ec7b00013126', '警告色', 'Warning', '警告色です', '警告色', '2024-08-15 09:27:43.721', '2024-08-15 09:27:43.721');
+INSERT INTO "public"."Internalization" VALUES ('6d1381b5-5ee0-4b46-895e-2a07525ebec5', 'error', 'f3bd1511-1cb7-45c1-8c3b-ec7b00013126', '错误色', 'Error', 'エラーカラーです', '錯誤色', '2024-08-15 09:28:12.143', '2024-08-15 09:28:12.143');
+INSERT INTO "public"."Internalization" VALUES ('a04920a6-ee2e-4c73-b85a-c3d790e0ba52', 'followPrimary', 'f3bd1511-1cb7-45c1-8c3b-ec7b00013126', '跟随主色', 'Follow Primary', 'メインカラーに従います', '跟隨主色', '2024-08-15 09:28:45.85', '2024-08-15 09:28:45.85');
+INSERT INTO "public"."Internalization" VALUES ('343abb08-4a3d-42b2-850a-7fdd5c16eb65', 'scrollMode', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', NULL, NULL, NULL, NULL, '2024-08-15 09:29:54.354', '2024-08-15 09:29:54.354');
+INSERT INTO "public"."Internalization" VALUES ('9860286b-49f7-47bf-b188-80d30422ba11', 'title', '343abb08-4a3d-42b2-850a-7fdd5c16eb65', '滚动模式', 'Scroll Mode', 'スクロールモードです', '滾動模式', '2024-08-15 09:30:19.501', '2024-08-15 09:30:19.501');
+INSERT INTO "public"."Internalization" VALUES ('a1b712ad-c5c5-41ec-bb9d-eef01811f151', 'wrapper', '343abb08-4a3d-42b2-850a-7fdd5c16eb65', '外层滚动', 'Wrapper', '外側が転がります', '外層滾動', '2024-08-15 09:30:44.641', '2024-08-15 09:30:44.641');
+INSERT INTO "public"."Internalization" VALUES ('9d551336-7e9a-41cf-9f07-27d125123967', 'content', '343abb08-4a3d-42b2-850a-7fdd5c16eb65', '主体滚动', 'Main Scroll', 'スクロールします', '主體滾動', '2024-08-15 09:31:29.983', '2024-08-15 09:31:29.983');
+INSERT INTO "public"."Internalization" VALUES ('4755ce71-0f46-4c57-87bc-2556516871bb', 'components', NULL, NULL, NULL, NULL, NULL, '2024-08-15 09:51:31.451', '2024-08-15 09:51:31.451');
+INSERT INTO "public"."Internalization" VALUES ('75cb2a61-3b16-46ce-ade0-03f30415f39c', 'strengthMeter', '4755ce71-0f46-4c57-87bc-2556516871bb', NULL, NULL, NULL, NULL, '2024-08-15 09:51:42.391', '2024-08-15 09:51:42.391');
+INSERT INTO "public"."Internalization" VALUES ('fb14ff77-55af-4a64-bd0a-77fc42ff76d4', 'veryWeak', '75cb2a61-3b16-46ce-ade0-03f30415f39c', '非常弱', 'VeryWeak', 'とても弱いです', '非常弱', '2024-08-15 09:52:45.084', '2024-08-15 09:52:45.084');
+INSERT INTO "public"."Internalization" VALUES ('937edc69-d5ff-4202-90c5-eac7fbe599c0', 'weak', '75cb2a61-3b16-46ce-ade0-03f30415f39c', '弱', 'Weak', '弱いです', '弱', '2024-08-15 09:53:15.191', '2024-08-15 09:53:15.191');
+INSERT INTO "public"."Internalization" VALUES ('f923979e-1fd3-4130-b8e4-be5daff455a1', 'general', '75cb2a61-3b16-46ce-ade0-03f30415f39c', '一般', 'General', '普通です', '壹般', '2024-08-15 09:53:46.24', '2024-08-15 09:53:46.24');
+INSERT INTO "public"."Internalization" VALUES ('ee8b1c8e-10a9-42f0-9d01-655ddf5ac383', 'strong', '75cb2a61-3b16-46ce-ade0-03f30415f39c', '强', 'Strong', '強いです', '強', '2024-08-15 09:54:13.801', '2024-08-15 09:54:13.801');
+INSERT INTO "public"."Internalization" VALUES ('5146e274-5ca5-4b4f-ab59-d3cea1ba434c', 'veryStrong', '75cb2a61-3b16-46ce-ade0-03f30415f39c', '非常强', 'VeryStrong', 'とても強いです', '非常強', '2024-08-15 09:54:36.921', '2024-08-15 09:54:36.921');
+INSERT INTO "public"."Internalization" VALUES ('74b6ac9d-e797-488b-92e4-36c9bfd2235a', 'icon', NULL, NULL, NULL, NULL, NULL, '2024-08-15 10:00:29.747', '2024-08-15 10:00:29.747');
+INSERT INTO "public"."Internalization" VALUES ('9fea13b0-af51-49ac-a4f8-9d69076e9892', 'no', '1dc06aff-fc1e-4caf-91f1-a13bf88ebe3a', '否', 'No', 'いいえ', '否', '2024-08-20 03:19:48.844', '2024-08-20 03:19:48.844');
+INSERT INTO "public"."Internalization" VALUES ('6cf17586-803d-432f-8086-ad42ff84ce9e', 'themeConfig', '74b6ac9d-e797-488b-92e4-36c9bfd2235a', '主题配置', 'Theme Configuration', 'テーマ配置です', '主題配置', '2024-08-15 10:01:04.898', '2024-08-15 10:01:04.898');
+INSERT INTO "public"."Internalization" VALUES ('ad8751ba-729e-4695-8f49-85d4cb5f2ab8', 'themeSchema', '74b6ac9d-e797-488b-92e4-36c9bfd2235a', '主题模式', 'Theme Schema', 'テーマモードです', '主題模式', '2024-08-15 10:01:38.166', '2024-08-15 10:01:38.166');
+INSERT INTO "public"."Internalization" VALUES ('eaeb929a-75bd-48b7-88ee-e7e18e903db8', 'lang', '74b6ac9d-e797-488b-92e4-36c9bfd2235a', '切换语言', 'Switch Language', '言語を切り替えます', '切換語言', '2024-08-15 10:02:09.457', '2024-08-15 10:02:09.457');
+INSERT INTO "public"."Internalization" VALUES ('cf65e673-0cc9-456a-8d44-ad20e861b480', 'fullscreen', '74b6ac9d-e797-488b-92e4-36c9bfd2235a', '全屏', 'Fullscreen', '全画面です', '全屏', '2024-08-15 10:02:38.558', '2024-08-15 10:02:38.558');
+INSERT INTO "public"."Internalization" VALUES ('a6e0457e-05a1-4105-9985-d8256f694fcc', 'fullscreenExit', '74b6ac9d-e797-488b-92e4-36c9bfd2235a', '退出全屏', 'Exit Fullscreen', '全画面から退出します', '退出全屏', '2024-08-15 10:03:07.913', '2024-08-15 10:03:07.913');
+INSERT INTO "public"."Internalization" VALUES ('4be1669c-f585-494e-beac-bcff83ade297', 'reload', '74b6ac9d-e797-488b-92e4-36c9bfd2235a', '刷新页面', 'Reload Page', 'ページを更新します', '刷新頁面', '2024-08-15 10:03:43.867', '2024-08-15 10:03:43.867');
+INSERT INTO "public"."Internalization" VALUES ('6a46c989-7a5a-4f10-a655-6220b105847c', 'collapse', '74b6ac9d-e797-488b-92e4-36c9bfd2235a', '折叠菜单', 'Collapse Menu', '折りたたみメニュー', '折疊菜單', '2024-08-15 10:05:21.244', '2024-08-15 10:05:21.244');
+INSERT INTO "public"."Internalization" VALUES ('672f1859-8c00-49b8-bb2f-510d107f88fd', 'expand', '74b6ac9d-e797-488b-92e4-36c9bfd2235a', '展开菜单', 'Expand Menu', 'メニューを展開します', '展開菜單', '2024-08-15 10:05:45.251', '2024-08-15 10:05:45.251');
+INSERT INTO "public"."Internalization" VALUES ('da744fe5-937c-4875-a2fd-887c9b6a69d1', 'pin', '74b6ac9d-e797-488b-92e4-36c9bfd2235a', '固定', 'Pin', '固定します', '固定', '2024-08-15 10:06:14.391', '2024-08-15 10:06:14.391');
+INSERT INTO "public"."Internalization" VALUES ('60af3e1c-a87c-4a9a-9cd3-167db41a72e9', 'unpin', '74b6ac9d-e797-488b-92e4-36c9bfd2235a', '取消固定', 'Unpin', '固定をなくします', '取消固定', '2024-08-15 10:06:41.599', '2024-08-15 10:06:41.599');
+INSERT INTO "public"."Internalization" VALUES ('84a11ddc-1b50-4636-a6b5-7ee9f07801bf', 'dropdown', NULL, NULL, NULL, NULL, NULL, '2024-08-15 10:06:58.819', '2024-08-15 10:06:58.819');
+INSERT INTO "public"."Internalization" VALUES ('85599a3d-013b-4c6c-acc9-cb197d6ce94a', 'closeCurrent', '84a11ddc-1b50-4636-a6b5-7ee9f07801bf', '关闭', 'Close Current', '閉鎖します', '關閉', '2024-08-15 10:07:41.314', '2024-08-15 10:07:41.314');
+INSERT INTO "public"."Internalization" VALUES ('25fcc642-5f95-4331-8f60-5d0f0880b23c', 'closeOther', '84a11ddc-1b50-4636-a6b5-7ee9f07801bf', '关闭其它', 'Close Other', 'その他は閉鎖します', '關閉其它', '2024-08-15 10:08:06.719', '2024-08-15 10:08:06.719');
+INSERT INTO "public"."Internalization" VALUES ('3c32ff37-864d-4ef2-8052-8facdc96ac5b', 'closeLeft', '84a11ddc-1b50-4636-a6b5-7ee9f07801bf', '关闭左侧', 'Close Left', '左側を閉じます', '關閉左側', '2024-08-15 10:08:37.145', '2024-08-15 10:08:37.145');
+INSERT INTO "public"."Internalization" VALUES ('65c785ef-68bd-4aad-ae8d-9861a773a58a', 'closeRight', '84a11ddc-1b50-4636-a6b5-7ee9f07801bf', '关闭右侧', 'Close Right', '右側を閉じます', '關閉右側', '2024-08-15 10:09:02.131', '2024-08-15 10:09:02.131');
+INSERT INTO "public"."Internalization" VALUES ('81f67c30-cebc-4d1f-b8eb-ab98d7c2444c', 'closeAll', '84a11ddc-1b50-4636-a6b5-7ee9f07801bf', '关闭所有', 'Close All', 'すべて閉鎖します', '關閉所有', '2024-08-15 10:09:25.134', '2024-08-15 10:09:25.134');
+INSERT INTO "public"."Internalization" VALUES ('1df58855-e0e0-4b79-b321-b45b8b3afebd', 'page', NULL, NULL, NULL, NULL, NULL, '2024-08-15 10:10:04.332', '2024-08-15 10:10:04.332');
+INSERT INTO "public"."Internalization" VALUES ('ea1839ad-c98f-49eb-a6c3-12ad1ac7a37a', 'login', '1df58855-e0e0-4b79-b321-b45b8b3afebd', NULL, NULL, NULL, NULL, '2024-08-15 10:10:12.735', '2024-08-15 10:10:12.735');
+INSERT INTO "public"."Internalization" VALUES ('d5a5dd6a-c647-4d98-b40d-3be397d091fb', 'userNamePlaceholder', 'ea1839ad-c98f-49eb-a6c3-12ad1ac7a37a', '请输入用户名', 'Please enter user name', 'ユーザー名の入力をお願いします', '請輸入用戶名', '2024-08-15 10:10:42.73', '2024-08-15 10:10:42.73');
+INSERT INTO "public"."Internalization" VALUES ('c3628009-133b-4f1b-bd5c-4cb39bf2b540', 'passwordPlaceholder', 'ea1839ad-c98f-49eb-a6c3-12ad1ac7a37a', '请输入密码', 'Please enter password', 'パスワードをお願いします', '請輸入密碼', '2024-08-15 10:11:42.944', '2024-08-15 10:11:42.944');
+INSERT INTO "public"."Internalization" VALUES ('3260bd66-3fd6-48f1-81d2-6054e932aeb2', 'codePlaceholder', 'ea1839ad-c98f-49eb-a6c3-12ad1ac7a37a', '请输入验证码', 'Please enter verification code', 'captcha入力をお願いします。', '請輸入驗證碼', '2024-08-15 10:12:14.826', '2024-08-15 10:12:14.826');
+INSERT INTO "public"."Internalization" VALUES ('c49262e0-239a-46d5-b6b0-294a78500910', 'loginSuccess', 'ea1839ad-c98f-49eb-a6c3-12ad1ac7a37a', '登录成功', 'Login successfully', 'ログインできました', '登錄成功', '2024-08-15 10:12:41.236', '2024-08-15 10:12:41.236');
+INSERT INTO "public"."Internalization" VALUES ('582490ac-90de-4e17-b076-98b1f958e38a', 'welcomeBack', 'ea1839ad-c98f-49eb-a6c3-12ad1ac7a37a', '欢迎回来,{cnName} !', 'Welcome back, {cnName} !', 'お帰りなさい,{cnName} !', '歡迎回來,{cnName} !', '2024-08-15 10:13:15.975', '2024-08-15 10:13:15.975');
+INSERT INTO "public"."Internalization" VALUES ('9eac8021-68e5-4458-962e-a9dbb92cd842', 'about', '1df58855-e0e0-4b79-b321-b45b8b3afebd', NULL, NULL, NULL, NULL, '2024-08-15 10:13:45.944', '2024-08-15 10:13:45.944');
+INSERT INTO "public"."Internalization" VALUES ('791f6dd4-7db9-4bd2-b551-eab3199098bb', 'title', '9eac8021-68e5-4458-962e-a9dbb92cd842', '关于', 'About', 'についてです', '關于', '2024-08-15 10:14:44.667', '2024-08-15 10:14:44.667');
+INSERT INTO "public"."Internalization" VALUES ('b0e5df59-cb28-41f1-aa92-b9ff3306225c', 'projectInfo', '9eac8021-68e5-4458-962e-a9dbb92cd842', NULL, NULL, NULL, NULL, '2024-08-15 10:15:49.34', '2024-08-15 10:15:49.34');
+INSERT INTO "public"."Internalization" VALUES ('6eabc31f-54a2-4e0a-b1e4-38e9a62629aa', 'title', 'b0e5df59-cb28-41f1-aa92-b9ff3306225c', '项目信息', 'Project Info', 'プロジェクト情報です', '項目信息', '2024-08-15 10:16:25.196', '2024-08-15 10:16:25.196');
+INSERT INTO "public"."Internalization" VALUES ('c73f1096-8c26-4d94-9fda-89020eb6bb70', 'version', 'b0e5df59-cb28-41f1-aa92-b9ff3306225c', '版本', 'Version', 'バージョンです', '版本', '2024-08-15 10:16:53.015', '2024-08-15 10:16:53.015');
+INSERT INTO "public"."Internalization" VALUES ('27248202-3275-4c37-904d-6e3ebe712a66', 'latestBuildTime', 'b0e5df59-cb28-41f1-aa92-b9ff3306225c', '最新构建时间', 'Latest Build Time', '最新の構築時期です', '最新構建時間', '2024-08-15 10:17:18.161', '2024-08-15 10:17:18.161');
+INSERT INTO "public"."Internalization" VALUES ('4628fbcb-5f0a-49ca-9401-623d683be30a', 'githubLink', 'b0e5df59-cb28-41f1-aa92-b9ff3306225c', 'Github 地址', 'Github Link', 'Githubアドレスです', 'Github 地址', '2024-08-15 10:17:42.924', '2024-08-15 10:17:42.924');
+INSERT INTO "public"."Internalization" VALUES ('fdb41e21-f32b-4251-a032-84e454966155', 'previewLink', 'b0e5df59-cb28-41f1-aa92-b9ff3306225c', '预览地址', 'Preview Link', 'プレビューアドレスです', '預覽地址', '2024-08-15 10:18:16.21', '2024-08-15 10:18:16.21');
+INSERT INTO "public"."Internalization" VALUES ('2b73720e-3c0f-454d-80e0-898577db8d71', 'prdDep', '9eac8021-68e5-4458-962e-a9dbb92cd842', '生产依赖', 'Production Dependency', '生産依存症です', '生産依賴', '2024-08-15 10:18:45.537', '2024-08-15 10:18:45.537');
+INSERT INTO "public"."Internalization" VALUES ('85f8c062-5037-498a-9b00-fbd35fe633b4', 'devDep', '9eac8021-68e5-4458-962e-a9dbb92cd842', '开发依赖', 'Development Dependency', '開発依存です', '開發依賴', '2024-08-15 10:19:09.863', '2024-08-15 10:19:09.863');
+INSERT INTO "public"."Internalization" VALUES ('9c98dd9d-c3cb-434b-a59c-bf96f9236d8e', 'home', '1df58855-e0e0-4b79-b321-b45b8b3afebd', NULL, NULL, NULL, NULL, '2024-08-15 10:20:17.328', '2024-08-15 10:20:17.328');
+INSERT INTO "public"."Internalization" VALUES ('555a4628-d9f2-4351-b55a-c7ad3061e43c', 'projectCount', '9c98dd9d-c3cb-434b-a59c-bf96f9236d8e', '项目数', 'Project Count', '項目数です', '項目數', '2024-08-15 10:22:26.926', '2024-08-15 10:22:26.926');
+INSERT INTO "public"."Internalization" VALUES ('09691ce9-e71a-4df0-924d-ea071f3a606c', 'todo', '9c98dd9d-c3cb-434b-a59c-bf96f9236d8e', '待办', 'Todo', '待ちます', '待辦', '2024-08-15 10:22:57.646', '2024-08-15 10:22:57.646');
+INSERT INTO "public"."Internalization" VALUES ('16716843-c668-497b-a352-abb2ca813d93', 'message', '9c98dd9d-c3cb-434b-a59c-bf96f9236d8e', '消息', 'message', 'メッセージです', '消息', '2024-08-15 10:23:26.157', '2024-08-15 10:23:26.157');
+INSERT INTO "public"."Internalization" VALUES ('42387aed-abc1-4273-8019-9361acf3e487', 'projectNews', '9c98dd9d-c3cb-434b-a59c-bf96f9236d8e', NULL, NULL, NULL, NULL, '2024-08-16 01:19:32.241', '2024-08-16 01:19:32.241');
+INSERT INTO "public"."Internalization" VALUES ('ceb410b0-6d54-47bd-82b8-cfcf0208c19b', 'title', '42387aed-abc1-4273-8019-9361acf3e487', '项目动态', 'Project News', 'プロジェクトの動きです', '項目動態', '2024-08-16 01:19:57.425', '2024-08-16 01:19:57.425');
+INSERT INTO "public"."Internalization" VALUES ('499b6f94-792a-4371-802a-9a0f2c752546', 'moreNews', '42387aed-abc1-4273-8019-9361acf3e487', '更多动态', 'More News', 'もっとダイナミックです', '更多動態', '2024-08-16 01:20:23.645', '2024-08-16 01:20:23.645');
+INSERT INTO "public"."Internalization" VALUES ('be1235ea-a62d-4c17-9932-bc42e26a58be', 'administrative', '1df58855-e0e0-4b79-b321-b45b8b3afebd', NULL, NULL, NULL, NULL, '2024-08-16 01:36:55.814', '2024-08-16 01:36:55.814');
+INSERT INTO "public"."Internalization" VALUES ('56ad5247-c67c-4c87-a4f3-a218ba54dd6b', 'organization', 'be1235ea-a62d-4c17-9932-bc42e26a58be', NULL, NULL, NULL, NULL, '2024-08-16 01:37:03.543', '2024-08-16 01:37:03.543');
+INSERT INTO "public"."Internalization" VALUES ('6f4a5a0e-b198-4a61-a46d-516e6a28468a', 'name', '56ad5247-c67c-4c87-a4f3-a218ba54dd6b', '组织名称', 'Organization name', '組織名です', '組織名稱', '2024-08-16 01:37:30.628', '2024-08-16 01:37:30.628');
+INSERT INTO "public"."Internalization" VALUES ('b026cfe2-d3b6-4265-a36c-4ad35311a83d', 'code', '56ad5247-c67c-4c87-a4f3-a218ba54dd6b', '组织编码', 'Organization code', '組織コードです', '組織編碼', '2024-08-16 01:37:58.818', '2024-08-16 01:37:58.818');
+INSERT INTO "public"."Internalization" VALUES ('f2238551-e011-4144-af04-70dd7690050e', 'posts', '56ad5247-c67c-4c87-a4f3-a218ba54dd6b', '关联岗位', 'Posts', '関連部署です', '關聯崗位', '2024-08-16 01:38:23.26', '2024-08-16 01:38:23.26');
+INSERT INTO "public"."Internalization" VALUES ('ed173ff2-d09e-47a6-9bb6-f26a044abb69', 'description', '56ad5247-c67c-4c87-a4f3-a218ba54dd6b', '组织描述', 'Description', '組織記述です', '組織描述', '2024-08-16 01:38:50.157', '2024-08-16 01:38:50.157');
+INSERT INTO "public"."Internalization" VALUES ('e6bfac5a-c0db-4878-999f-cf59ca0ac2d5', 'icon', '56ad5247-c67c-4c87-a4f3-a218ba54dd6b', '组织图标', 'Organization Icon', '組織のアイコンです', '組織圖標', '2024-08-16 01:39:18.897', '2024-08-16 01:39:18.897');
+INSERT INTO "public"."Internalization" VALUES ('a5459e51-940c-441d-b032-576bc6d968ed', 'iconTip', '56ad5247-c67c-4c87-a4f3-a218ba54dd6b', '请查看官网系统图标用法', 'Please check the system icon usage on the official website', '公式サイトのシステムアイコンの使い方をご覧になります', '請查看官網系統圖標用法', '2024-08-16 01:39:44.622', '2024-08-16 01:39:44.622');
+INSERT INTO "public"."Internalization" VALUES ('f7b323d6-8d96-4712-9b01-a9c2d9abae7f', 'addOrg', '56ad5247-c67c-4c87-a4f3-a218ba54dd6b', '新增组织', 'Add Organization', '組織を増やします', '新增組織', '2024-08-16 01:40:08.384', '2024-08-16 01:40:08.384');
+INSERT INTO "public"."Internalization" VALUES ('7b1f6eae-e307-4709-8b02-fa487062224b', 'editOrg', '56ad5247-c67c-4c87-a4f3-a218ba54dd6b', '编辑组织', 'Edit Organization', '組織を編集します', '編輯組織', '2024-08-16 01:40:31.825', '2024-08-16 01:40:31.825');
+INSERT INTO "public"."Internalization" VALUES ('5cdb8bf9-b968-42de-9fbe-088a3f886911', 'postManage', 'be1235ea-a62d-4c17-9932-bc42e26a58be', NULL, NULL, NULL, NULL, '2024-08-16 01:40:38.865', '2024-08-16 01:40:38.865');
+INSERT INTO "public"."Internalization" VALUES ('646aba3a-e9b5-4b5e-949f-89b2f6b88078', 'name', '5cdb8bf9-b968-42de-9fbe-088a3f886911', '岗位名称', 'Post Name', '持ち場の名前です', '崗位名稱', '2024-08-16 01:41:06.179', '2024-08-16 01:41:06.179');
+INSERT INTO "public"."Internalization" VALUES ('16aaf4a6-3c10-4ad8-92bf-867a831f506b', 'orgId', '5cdb8bf9-b968-42de-9fbe-088a3f886911', '所属组织', 'Organization', '所属組織です', '所屬組織', '2024-08-16 01:41:31.228', '2024-08-16 01:41:31.228');
+INSERT INTO "public"."Internalization" VALUES ('9a57c674-de4b-49da-acc8-6a041a0319f3', 'description', '5cdb8bf9-b968-42de-9fbe-088a3f886911', '岗位描述', 'Description', '職務記述です', '崗位描述', '2024-08-16 01:41:54.351', '2024-08-16 01:41:54.351');
+INSERT INTO "public"."Internalization" VALUES ('37ee026c-6568-4267-88e2-2c98afd2749d', 'addPost', '5cdb8bf9-b968-42de-9fbe-088a3f886911', '新增岗位', 'Add Post', '新たに雇用を増やす', '新增崗位', '2024-08-16 01:42:19.331', '2024-08-16 01:42:19.331');
+INSERT INTO "public"."Internalization" VALUES ('3afc2158-1d69-46e1-a54a-a2d1a525d485', 'editPost', '5cdb8bf9-b968-42de-9fbe-088a3f886911', '编辑岗位', 'Edit Post', '編集の部署です', '編輯崗位', '2024-08-16 01:42:48.621', '2024-08-16 01:42:48.621');
+INSERT INTO "public"."Internalization" VALUES ('c722a9a1-2d00-4281-9155-c7b2845080f2', 'systemManage', '1df58855-e0e0-4b79-b321-b45b8b3afebd', NULL, NULL, NULL, NULL, '2024-08-16 01:43:12.843', '2024-08-16 01:43:12.843');
+INSERT INTO "public"."Internalization" VALUES ('598aa0c9-2176-45e1-a66f-bea42863b03f', 'userManage', 'c722a9a1-2d00-4281-9155-c7b2845080f2', NULL, NULL, NULL, NULL, '2024-08-16 01:43:18.707', '2024-08-16 01:43:18.707');
+INSERT INTO "public"."Internalization" VALUES ('bffb8b82-730e-46fa-8210-d79cf933445e', 'userName', '598aa0c9-2176-45e1-a66f-bea42863b03f', '用户名', 'UserName', 'ユーザー名です', '用戶名', '2024-08-16 01:43:42.268', '2024-08-16 01:43:42.268');
+INSERT INTO "public"."Internalization" VALUES ('84e2c72a-bf44-47cb-a797-7e5ce4de79f8', 'blogLog', '9c98dd9d-c3cb-434b-a59c-bf96f9236d8e', '博客日志', 'Blog log', 'ブログ日誌', '博客日誌', '2024-08-16 01:23:24.345', '2024-09-04 06:58:17.137');
+INSERT INTO "public"."Internalization" VALUES ('9b43cc93-2cbe-4bc7-964e-6ef75e4cb0b2', 'userNameTip', '598aa0c9-2176-45e1-a66f-bea42863b03f', '用户名由4到16位(字母,数字,下划线,减号)组成', 'The user name consists of 4 to 16 characters (letters, numbers, underscores, and minus signs)', 'ユーザー名は4 ~ 16ビット(アルファベット、数字、アンダーライン、マイナス)からなります', '用戶名由4到16位(字母,數字,下劃線,減號)組成', '2024-08-16 01:44:11.521', '2024-08-16 01:44:11.521');
+INSERT INTO "public"."Internalization" VALUES ('a68dea9f-69b2-4a13-93bb-d82c458fcdf9', 'cnName', '598aa0c9-2176-45e1-a66f-bea42863b03f', '中文名', 'CnName', '日文名です', '中文名', '2024-08-16 01:44:34.679', '2024-08-16 01:44:34.679');
+INSERT INTO "public"."Internalization" VALUES ('129c9dfd-b3aa-43c6-b324-bbb088c8037b', 'phone', '598aa0c9-2176-45e1-a66f-bea42863b03f', '手机号码', 'Phone', '携帯電話番号です', '手機號碼', '2024-08-16 01:44:56.533', '2024-08-16 01:44:56.533');
+INSERT INTO "public"."Internalization" VALUES ('4dd572d7-25dd-4c82-b730-5f6ba12b5e77', 'phoneTip', '598aa0c9-2176-45e1-a66f-bea42863b03f', '手机号码格式不正确', 'The mobile phone number format is incorrect', '携帯電話の番号が正しくありません', '手機號碼格式不正確', '2024-08-16 01:45:28.14', '2024-08-16 01:45:28.14');
+INSERT INTO "public"."Internalization" VALUES ('ff03e88c-9b39-43ae-b7ca-d9c69f6a4f43', 'email', '598aa0c9-2176-45e1-a66f-bea42863b03f', '电子邮箱', 'Email', 'eメールです', '電子郵箱', '2024-08-16 01:45:52.277', '2024-08-16 01:45:52.277');
+INSERT INTO "public"."Internalization" VALUES ('67f2bb5b-8e2c-4480-9929-03fa01101f87', 'emailTip', '598aa0c9-2176-45e1-a66f-bea42863b03f', '电子邮箱地址格式不正确', 'The email address format is incorrect', 'eメールアドレスのフォーマットが正しくありません', '電子郵箱地址格式不正確', '2024-08-16 01:46:20.203', '2024-08-16 01:46:20.203');
+INSERT INTO "public"."Internalization" VALUES ('28292158-9603-42ae-9d1c-70eeb9abf429', 'sex', '598aa0c9-2176-45e1-a66f-bea42863b03f', '性别', 'Sex', '性別です', '性別', '2024-08-16 01:46:40.159', '2024-08-16 01:46:40.159');
+INSERT INTO "public"."Internalization" VALUES ('182851c4-064c-4326-80fd-e12bd7556c3b', 'orgId', '598aa0c9-2176-45e1-a66f-bea42863b03f', '所属组织', 'Organization', '所属組織です', '所屬組織', '2024-08-16 01:47:00.492', '2024-08-16 01:47:00.492');
+INSERT INTO "public"."Internalization" VALUES ('09c93088-44ea-4129-8362-e296a1529822', 'postId', '598aa0c9-2176-45e1-a66f-bea42863b03f', '所属岗位', 'Post', '所属部署です', '所屬崗位', '2024-08-16 01:47:27.475', '2024-08-16 01:47:27.475');
+INSERT INTO "public"."Internalization" VALUES ('000be5db-4465-459a-9868-4620ae48e163', 'city', '598aa0c9-2176-45e1-a66f-bea42863b03f', '所属城市', 'City', '所属する都市', '所屬城市', '2024-08-16 01:47:51.337', '2024-08-16 01:47:51.337');
+INSERT INTO "public"."Internalization" VALUES ('8d96bf08-d151-4979-8817-f231a8f4ede0', 'address', '598aa0c9-2176-45e1-a66f-bea42863b03f', '详细地址', 'Address', '詳しい住所です', '詳細地址', '2024-08-16 01:48:12.618', '2024-08-16 01:48:12.618');
+INSERT INTO "public"."Internalization" VALUES ('4beb5f11-1a4d-4d7c-b0c9-f0d4bbc494ab', 'tags', '598aa0c9-2176-45e1-a66f-bea42863b03f', '人物标签', 'Tags', '人物タグです', '人物標簽', '2024-08-16 01:48:39.18', '2024-08-16 01:48:39.18');
+INSERT INTO "public"."Internalization" VALUES ('ad502055-a942-4b1f-a4b8-393bfa5a2658', 'addUser', '598aa0c9-2176-45e1-a66f-bea42863b03f', '新增用户', 'Add User', '新規加入者です', '新增用戶', '2024-08-16 01:49:03.622', '2024-08-16 01:49:03.622');
+INSERT INTO "public"."Internalization" VALUES ('ff3c435b-9e7d-42e7-b2e0-f83afa42e3bd', 'editUser', '598aa0c9-2176-45e1-a66f-bea42863b03f', '编辑用户', 'Edit User', '編集ユーザーです', '編輯用戶', '2024-08-16 01:49:27.62', '2024-08-16 01:49:27.62');
+INSERT INTO "public"."Internalization" VALUES ('11c088fc-1c4f-4e78-ad2a-9a291433ee91', 'personalInfo', '598aa0c9-2176-45e1-a66f-bea42863b03f', '个人信息', 'Personal Info', '個人情報です', '個人信息', '2024-08-16 01:49:50.808', '2024-08-16 01:49:50.808');
+INSERT INTO "public"."Internalization" VALUES ('f8dcedae-5185-462b-9063-b86c81b8d9a1', 'userInfo', '598aa0c9-2176-45e1-a66f-bea42863b03f', '用户信息', 'User Info', 'ユーザー情報です', '用戶信息', '2024-08-16 01:50:12.908', '2024-08-16 01:50:12.908');
+INSERT INTO "public"."Internalization" VALUES ('bb79e0ab-da9c-4a0b-afe5-e49657dbcd8b', 'settingAvatar', '598aa0c9-2176-45e1-a66f-bea42863b03f', '设置头像', 'Setting Avatar', 'プロフィール画像を設定します', '設置頭像', '2024-08-16 01:50:34.192', '2024-08-16 01:50:34.192');
+INSERT INTO "public"."Internalization" VALUES ('2c6c1317-f448-4cad-ae3f-457eda6a1dda', 'settingPassword', '598aa0c9-2176-45e1-a66f-bea42863b03f', '设置密码', 'Setting Password', 'パスワードを設定します', '設置密碼', '2024-08-16 01:50:55.745', '2024-08-16 01:50:55.745');
+INSERT INTO "public"."Internalization" VALUES ('4cbd6deb-de5b-42de-90b6-bffae325f30d', 'confirmPassword', '598aa0c9-2176-45e1-a66f-bea42863b03f', '确认密码', 'Comfirm Password', 'パスワードを確認します', '確認密碼', '2024-08-16 01:51:40.584', '2024-08-16 01:51:40.584');
+INSERT INTO "public"."Internalization" VALUES ('b0ef7393-fcd5-4a13-8787-6e453683387b', 'avatar', '598aa0c9-2176-45e1-a66f-bea42863b03f', '头像', 'Avatar', 'アイコン', '頭像', '2024-08-16 01:52:00.762', '2024-08-16 01:52:00.762');
+INSERT INTO "public"."Internalization" VALUES ('8b370f89-44ff-4381-afca-c56339c0aa48', 'sexMap', '598aa0c9-2176-45e1-a66f-bea42863b03f', NULL, NULL, NULL, NULL, '2024-08-16 01:52:10.023', '2024-08-16 01:52:10.023');
+INSERT INTO "public"."Internalization" VALUES ('48bfd064-9de3-40c9-9373-d0b1af1fd233', 'male', '8b370f89-44ff-4381-afca-c56339c0aa48', '男', 'Male', '男です', '男', '2024-08-16 01:52:31.442', '2024-08-16 01:52:31.442');
+INSERT INTO "public"."Internalization" VALUES ('dea2ad0f-3062-4d8f-b533-e84e2dc58d71', 'female', '8b370f89-44ff-4381-afca-c56339c0aa48', '女', 'Female', '女です', '女', '2024-08-16 01:52:54.706', '2024-08-16 01:52:54.706');
+INSERT INTO "public"."Internalization" VALUES ('e4b6c671-26d8-4efd-8beb-120b5256adb8', 'internalization', 'c722a9a1-2d00-4281-9155-c7b2845080f2', NULL, NULL, NULL, NULL, '2024-08-16 01:53:49.789', '2024-08-16 01:53:49.789');
+INSERT INTO "public"."Internalization" VALUES ('40dadfef-7a31-4040-9082-9f4a3474f4f6', 'name', 'e4b6c671-26d8-4efd-8beb-120b5256adb8', '国际化字段', 'Internalization Field', '国際化フィールドです', '國際化字段', '2024-08-16 01:54:11.421', '2024-08-16 01:54:11.421');
+INSERT INTO "public"."Internalization" VALUES ('4f173dbd-87ce-4e58-9f71-0855fb41c91d', 'zhCN', 'e4b6c671-26d8-4efd-8beb-120b5256adb8', '中文', 'Chinese', '中文', '中文', '2024-08-16 01:54:32.547', '2024-08-16 01:54:32.547');
+INSERT INTO "public"."Internalization" VALUES ('be325d62-7795-4f2d-8c19-c557ed245817', 'enUS', 'e4b6c671-26d8-4efd-8beb-120b5256adb8', '英文', 'English', '英語です', '英文', '2024-08-16 01:54:55.112', '2024-08-16 01:54:55.112');
+INSERT INTO "public"."Internalization" VALUES ('7c75c2de-f439-4f00-aecc-9b3b5d724b43', 'jaJP', 'e4b6c671-26d8-4efd-8beb-120b5256adb8', '日文', 'Japanese', '日本語です', '日文', '2024-08-16 01:55:17.29', '2024-08-16 01:55:17.29');
+INSERT INTO "public"."Internalization" VALUES ('5ae652d3-1b96-4396-a29d-5a13a4c47a11', 'zhTW', 'e4b6c671-26d8-4efd-8beb-120b5256adb8', '繁体中文', 'Traditional Chinese', '繁体中国語', '繁體中文', '2024-08-16 01:55:39.953', '2024-08-16 01:55:39.953');
+INSERT INTO "public"."Internalization" VALUES ('54dd0322-6b30-4476-9f69-049395e42dac', 'addInternalization', 'e4b6c671-26d8-4efd-8beb-120b5256adb8', '新增国际化', 'Add Internalization', '新たな国際化です', '新增國際化', '2024-08-16 01:56:03.269', '2024-08-16 01:56:03.269');
+INSERT INTO "public"."Internalization" VALUES ('14095da3-34d9-456b-ad36-bdae80d11f3e', 'editInternalization', 'e4b6c671-26d8-4efd-8beb-120b5256adb8', '编辑国际化', 'Edit Internalization', '編集インターナショナルです', '編輯國際化', '2024-08-16 01:56:26.569', '2024-08-16 01:56:26.569');
+INSERT INTO "public"."Internalization" VALUES ('3f05721e-70cd-4f93-bc94-f6f2951d935f', 'operationLog', 'c722a9a1-2d00-4281-9155-c7b2845080f2', NULL, NULL, NULL, NULL, '2024-08-16 01:57:03.948', '2024-08-16 01:57:03.948');
+INSERT INTO "public"."Internalization" VALUES ('047389b9-808a-404d-af91-04fbeaaf9b5c', 'userId', '3f05721e-70cd-4f93-bc94-f6f2951d935f', '操作用户', 'Operation User', 'ユーザーを操作します', '操作用戶', '2024-08-16 01:57:24.995', '2024-08-16 01:57:24.995');
+INSERT INTO "public"."Internalization" VALUES ('f7d5382c-664d-4d9f-aa93-e64bef7d265f', 'ip', '3f05721e-70cd-4f93-bc94-f6f2951d935f', 'ip', 'IP', 'ipです', 'ip', '2024-08-16 01:57:47.913', '2024-08-16 01:57:47.913');
+INSERT INTO "public"."Internalization" VALUES ('28e9dc1a-37be-4c66-8eb6-3fa42ba334b8', 'action', '3f05721e-70cd-4f93-bc94-f6f2951d935f', '请求接口', 'Action', '要求インターフェースです', '請求接口', '2024-08-16 01:58:10.778', '2024-08-16 01:58:10.778');
+INSERT INTO "public"."Internalization" VALUES ('04159a3d-5f04-4ad3-9a96-bda31423e974', 'method', '3f05721e-70cd-4f93-bc94-f6f2951d935f', '请求方法', 'Method', '請求方法です', '請求方法', '2024-08-16 01:58:31.567', '2024-08-16 01:58:31.567');
+INSERT INTO "public"."Internalization" VALUES ('c86cda5b-7dcf-48ae-b1c7-d2cb929cc9f1', 'browser', '3f05721e-70cd-4f93-bc94-f6f2951d935f', '浏览器', 'Browser', 'ブラウザです', '瀏覽器', '2024-08-16 01:59:24.17', '2024-08-16 01:59:24.17');
+INSERT INTO "public"."Internalization" VALUES ('2b85664c-ea80-4401-981a-e93ad807d983', 'form', NULL, NULL, NULL, NULL, NULL, '2024-08-16 01:59:46.89', '2024-08-16 01:59:46.89');
+INSERT INTO "public"."Internalization" VALUES ('0ca42c8e-2a3a-4704-9b0d-06778e8e29c0', 'required', '2b85664c-ea80-4401-981a-e93ad807d983', '不能为空', 'Cannot be empty', '空にはできません', '不能為空', '2024-08-16 02:00:12.784', '2024-08-16 02:00:12.784');
+INSERT INTO "public"."Internalization" VALUES ('43bd707a-ae66-449e-9592-4a7cd2d7d70d', 'userName', '2b85664c-ea80-4401-981a-e93ad807d983', NULL, NULL, NULL, NULL, '2024-08-16 02:00:21.722', '2024-08-16 02:00:21.722');
+INSERT INTO "public"."Internalization" VALUES ('2fda3333-7fbe-4198-b2cf-7be02897e95d', 'os', '3f05721e-70cd-4f93-bc94-f6f2951d935f', '操作系统', 'OS', 'osです', '操作系統', '2024-08-16 01:59:00.516', '2024-08-16 08:04:47.739');
+INSERT INTO "public"."Internalization" VALUES ('32da6534-59cd-4143-a534-89e1bd4cc502', 'required', '43bd707a-ae66-449e-9592-4a7cd2d7d70d', '请输入用户名', 'Please enter user name', 'ユーザー名の入力をお願いします', '請輸入用戶名', '2024-08-16 02:00:48.999', '2024-08-16 02:00:48.999');
+INSERT INTO "public"."Internalization" VALUES ('b594a35d-2bd9-4b7a-8789-8279a4b195e9', 'phone', '2b85664c-ea80-4401-981a-e93ad807d983', NULL, NULL, NULL, NULL, '2024-08-16 02:01:18.313', '2024-08-16 02:01:18.313');
+INSERT INTO "public"."Internalization" VALUES ('c6fe369f-2428-4187-b387-738d9cbf4d64', 'required', 'b594a35d-2bd9-4b7a-8789-8279a4b195e9', '请输入手机号', 'Please enter phone number', '携帯番号の入力をお願いします', '請輸入手機號', '2024-08-16 02:02:07.479', '2024-08-16 02:02:07.479');
+INSERT INTO "public"."Internalization" VALUES ('3742c18b-7522-4aaf-a421-1056f64bb182', 'invalid', 'b594a35d-2bd9-4b7a-8789-8279a4b195e9', '手机号格式不正确', 'Phone number format is incorrect', '携帯電話番号のフォーマットが間違っています', '手機號格式不正確', '2024-08-16 02:02:31.385', '2024-08-16 02:02:31.385');
+INSERT INTO "public"."Internalization" VALUES ('fe26c557-488a-4108-a1e6-4323a17d8fc1', 'pwd', '2b85664c-ea80-4401-981a-e93ad807d983', NULL, NULL, NULL, NULL, '2024-08-16 02:02:39.267', '2024-08-16 02:02:39.267');
+INSERT INTO "public"."Internalization" VALUES ('fb8b398d-e9ea-4361-bbbb-21e71d5d2d7f', 'invalid', 'fe26c557-488a-4108-a1e6-4323a17d8fc1', '密码格式不正确,6-18位字符,包含字母、数字、下划线', '6-18 characters, including letters, numbers, and underscores', 'パスワードの書式は正しくありません、6-18桁の文字、アルファベット、数字、下線を含みます', '密碼格式不正確,6-18位字符,包含字母、數字、下劃線', '2024-08-16 02:03:32.911', '2024-08-16 02:03:32.911');
+INSERT INTO "public"."Internalization" VALUES ('39bc371c-adc1-4650-94d0-0e5e5a6a8977', 'invalid', 'bf6c8f7b-4c63-49a1-b243-d310bb4c10e1', '两次输入密码不一致', 'The two passwords are inconsistent', '2回入力してもパスワードが一致しません', '兩次輸入密碼不一致', '2024-08-16 02:07:30.475', '2024-08-16 02:07:30.475');
+INSERT INTO "public"."Internalization" VALUES ('49bb9e4f-8ddf-417e-8476-5cbee02b5980', 'code', '2b85664c-ea80-4401-981a-e93ad807d983', NULL, NULL, NULL, NULL, '2024-08-16 02:07:36.296', '2024-08-16 02:07:36.296');
+INSERT INTO "public"."Internalization" VALUES ('b354759d-1929-45a0-83eb-826ceca94059', 'required', '49bb9e4f-8ddf-417e-8476-5cbee02b5980', '请输入验证码', 'Please enter verification code', 'captcha入力をお願いします', '請輸入驗證碼', '2024-08-16 02:08:04.474', '2024-08-16 02:08:04.474');
+INSERT INTO "public"."Internalization" VALUES ('bdb7e52e-1aaa-4c0b-82e8-3524e385384d', 'invalid', '49bb9e4f-8ddf-417e-8476-5cbee02b5980', '验证码格式不正确', 'Verification code format is incorrect', 'captchaフォーマットが正しくありません', '驗證碼格式不正確', '2024-08-16 02:08:26.803', '2024-08-16 02:08:26.803');
+INSERT INTO "public"."Internalization" VALUES ('364bb642-4cc1-441f-904f-22e4c6a5f235', 'email', '2b85664c-ea80-4401-981a-e93ad807d983', NULL, NULL, NULL, NULL, '2024-08-16 02:08:33.6', '2024-08-16 02:08:33.6');
+INSERT INTO "public"."Internalization" VALUES ('49f351d4-b0da-45a7-a798-22d150adc5c9', 'status', '2b85664c-ea80-4401-981a-e93ad807d983', '状态', 'Status', '状態です', '狀態', '2024-08-16 02:09:41.143', '2024-08-16 02:09:41.143');
+INSERT INTO "public"."Internalization" VALUES ('26702162-6e09-4357-b750-fb1ca9d0b35c', 'inactive', '3d562aa3-d08b-4705-b2bb-e6192c9bc55a', '禁用', 'Forbidden', '無効です', '禁用', '2024-08-16 02:10:30.851', '2024-08-16 02:10:30.851');
+INSERT INTO "public"."Internalization" VALUES ('39b25253-e443-41f6-83cc-a7e6252d1422', 'select', '2b85664c-ea80-4401-981a-e93ad807d983', '请选择', 'Please select ', '選択をお願いします', '請選擇', '2024-08-16 02:11:29.672', '2024-08-16 02:11:29.672');
+INSERT INTO "public"."Internalization" VALUES ('9d469277-219f-4c5f-9dd6-5eaf555a2180', 'sort', '2b85664c-ea80-4401-981a-e93ad807d983', '排序', 'Sort', '順序付けです', '排序', '2024-08-16 02:12:04.196', '2024-08-16 02:12:04.196');
+INSERT INTO "public"."Internalization" VALUES ('3d34aa7e-82c4-444b-9adf-deaf73fd2ba4', 'invalid', '43bd707a-ae66-449e-9592-4a7cd2d7d70d', '用户名格式不正确', 'User name format is incorrect', 'ユーザー名のフォーマットが正しくありません', '用戶名格式不正確', '2024-08-16 02:01:11.315', '2024-08-16 02:01:11.315');
+INSERT INTO "public"."Internalization" VALUES ('8b7503ba-c86e-44e8-a52b-e22c1237e50f', 'required', 'fe26c557-488a-4108-a1e6-4323a17d8fc1', '请输入密码', 'Please enter password', 'パスワードをお願いします', '請輸入密碼', '2024-08-16 02:03:01.561', '2024-08-16 02:03:01.561');
+INSERT INTO "public"."Internalization" VALUES ('bf6c8f7b-4c63-49a1-b243-d310bb4c10e1', 'confirmPwd', '2b85664c-ea80-4401-981a-e93ad807d983', NULL, NULL, NULL, NULL, '2024-08-16 02:06:37.712', '2024-08-16 02:06:37.712');
+INSERT INTO "public"."Internalization" VALUES ('4452ed8e-a8f1-43ec-943b-c40ecbe27621', 'required', 'bf6c8f7b-4c63-49a1-b243-d310bb4c10e1', '请输入确认密码', 'Please enter password again', '確認パスワードをお願いします', '請輸入確認密碼', '2024-08-16 02:07:07.929', '2024-08-16 02:07:07.929');
+INSERT INTO "public"."Internalization" VALUES ('7f786981-f389-4cbd-bbdc-34c2db2885cc', 'required', '364bb642-4cc1-441f-904f-22e4c6a5f235', '请输入邮箱', 'Please enter email', 'メールをお願いします', '請輸入郵箱', '2024-08-16 02:08:56.899', '2024-08-16 02:08:56.899');
+INSERT INTO "public"."Internalization" VALUES ('17dc1c65-dffc-42e1-8a23-3909f8e20161', 'invalid', '364bb642-4cc1-441f-904f-22e4c6a5f235', '邮箱格式不正确', 'Email format is incorrect', 'メールのフォーマットが正しくありません', '郵箱格式不正確', '2024-08-16 02:09:19.104', '2024-08-16 02:09:19.104');
+INSERT INTO "public"."Internalization" VALUES ('3d562aa3-d08b-4705-b2bb-e6192c9bc55a', 'statusMap', '2b85664c-ea80-4401-981a-e93ad807d983', NULL, NULL, NULL, NULL, '2024-08-16 02:09:47.256', '2024-08-16 02:09:47.256');
+INSERT INTO "public"."Internalization" VALUES ('5f9fe011-bfa1-4aeb-958e-d1677129e0d6', 'active', '3d562aa3-d08b-4705-b2bb-e6192c9bc55a', '正常', 'Active', '正常です', '正常', '2024-08-16 02:10:08.603', '2024-08-16 02:10:08.603');
+INSERT INTO "public"."Internalization" VALUES ('c5187377-a556-4857-8eb9-0d22fdc6b03c', 'enter', '2b85664c-ea80-4401-981a-e93ad807d983', '请输入', 'Please enter ', '入力お願いします', '請輸入', '2024-08-16 02:10:48.475', '2024-08-16 02:11:43.719');
+INSERT INTO "public"."Internalization" VALUES ('2f64111d-48a3-4692-8e71-37e7bffb8c84', 'sortTip', '2b85664c-ea80-4401-981a-e93ad807d983', '排序越大,位置越靠前', 'The larger the order, the higher the position', '順位が大きいほど,位置が前になります', '排序越大,位置越靠前', '2024-08-16 02:12:29.631', '2024-08-16 02:12:29.631');
+INSERT INTO "public"."Internalization" VALUES ('737e42db-cf8b-4d33-86d7-80051850a52b', 'parent', '2b85664c-ea80-4401-981a-e93ad807d983', '父级', 'Parent', '父です', '父級', '2024-08-16 02:12:53.2', '2024-08-16 02:12:53.2');
+INSERT INTO "public"."Internalization" VALUES ('47177ad5-d8c1-471c-a663-c0fe63b00e5e', 'yes', '1dc06aff-fc1e-4caf-91f1-a13bf88ebe3a', '是', 'Yes', 'そうです', '是', '2024-08-20 03:19:25.391', '2024-08-20 03:19:25.391');
+INSERT INTO "public"."Internalization" VALUES ('33311958-4201-4883-b943-b90179489f18', 'parentTip', '2b85664c-ea80-4401-981a-e93ad807d983', '不选默认为顶级', 'The default is top-level', 'デフォルトトップを選ばないのです', '不選默認為頂級', '2024-08-16 02:13:14.925', '2024-08-16 02:13:14.925');
+INSERT INTO "public"."Internalization" VALUES ('0ae5a043-07b4-4943-935d-1e0996423a65', 'upload', '2b85664c-ea80-4401-981a-e93ad807d983', NULL, NULL, NULL, NULL, '2024-08-16 02:13:19.984', '2024-08-16 02:13:19.984');
+INSERT INTO "public"."Internalization" VALUES ('2077ab70-59ac-478a-a51e-f79f96f3ae41', 'limitSize', '0ae5a043-07b4-4943-935d-1e0996423a65', '文件大小不能超过{size}', 'The file size cannot exceed {size}', 'ファイルサイズは{size}を超えてはいけません', '文件大小不能超過{size}', '2024-08-16 02:13:44.882', '2024-08-16 02:13:44.882');
+INSERT INTO "public"."Internalization" VALUES ('9cbb4ed8-aa10-49ab-a5b0-d8c2739850e0', 'error', '0ae5a043-07b4-4943-935d-1e0996423a65', '文件上传失败', 'File upload failure', 'ファイルのアップロードに失敗しました', '文件上傳失敗', '2024-08-16 02:14:09.127', '2024-08-16 02:14:09.127');
+INSERT INTO "public"."Internalization" VALUES ('48e75d7f-ff26-42ba-9aea-ec673087f4f2', 'fileType', '0ae5a043-07b4-4943-935d-1e0996423a65', '只能上传 {type} 文件', 'Only {type} files can be uploaded', '{type}ファイルのみアップロードできます', '只能上傳 {type} 文件', '2024-08-16 02:14:31.543', '2024-08-16 02:14:31.543');
+INSERT INTO "public"."Internalization" VALUES ('f0f653d7-7ba7-49b3-8703-e8ed327810b9', 'page', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', NULL, NULL, NULL, NULL, '2024-08-16 06:30:49.249', '2024-08-16 06:30:49.249');
+INSERT INTO "public"."Internalization" VALUES ('ee441a62-fe9b-4af2-8ba2-0bff7d991a2f', 'animate', 'f0f653d7-7ba7-49b3-8703-e8ed327810b9', '页面切换动画', 'Page switch animation', 'ページ切り替えアニメーションです', '頁面切換動畫', '2024-08-16 06:31:25.705', '2024-08-16 06:31:25.705');
+INSERT INTO "public"."Internalization" VALUES ('74b90980-372a-4244-b0f5-4eff1808bc09', 'mode', 'f0f653d7-7ba7-49b3-8703-e8ed327810b9', NULL, NULL, NULL, NULL, '2024-08-16 06:31:41.572', '2024-08-16 06:31:41.572');
+INSERT INTO "public"."Internalization" VALUES ('b81e6056-8495-4653-b2a2-1b590c2df881', 'title', '74b90980-372a-4244-b0f5-4eff1808bc09', '页面切换动画类型', 'Page switch animation type', 'ページ切り替えアニメーションタイプです', '頁面切換動畫類型', '2024-08-16 06:32:11.924', '2024-08-16 06:32:11.924');
+INSERT INTO "public"."Internalization" VALUES ('35468601-0412-4337-8aa0-49ecffb01b25', 'fade-slide', '74b90980-372a-4244-b0f5-4eff1808bc09', '滑动', 'Slide', 'スライドします', '滑動', '2024-08-16 06:32:40.954', '2024-08-16 06:32:40.954');
+INSERT INTO "public"."Internalization" VALUES ('771cbb95-fd09-45de-9094-c26738ae94be', 'fade', '74b90980-372a-4244-b0f5-4eff1808bc09', '淡入淡出', 'Fade', '淡入フェードアウト', '淡入淡出', '2024-08-16 06:33:11.191', '2024-08-16 06:33:11.191');
+INSERT INTO "public"."Internalization" VALUES ('dd803933-0423-4563-a01b-bc7117360596', 'fade-bottom', '74b90980-372a-4244-b0f5-4eff1808bc09', '底部消退', 'Bottom extinction', '底が後退します', '底部消退', '2024-08-16 06:33:41.4', '2024-08-16 06:33:41.4');
+INSERT INTO "public"."Internalization" VALUES ('571789a9-1925-4853-b2c7-4f21534f845c', 'fade-scale', '74b90980-372a-4244-b0f5-4eff1808bc09', '缩放消退', 'Zoom extinction', 'ズーム後退です', '縮放消退', '2024-08-16 06:34:17.665', '2024-08-16 06:34:17.665');
+INSERT INTO "public"."Internalization" VALUES ('c503f072-0af7-4f93-a01b-c25752053a48', 'zoom-fade', '74b90980-372a-4244-b0f5-4eff1808bc09', '渐变', 'gradation', 'グラデーションです', '漸變', '2024-08-16 06:34:49.994', '2024-08-16 06:34:49.994');
+INSERT INTO "public"."Internalization" VALUES ('6c84e419-7dd1-4d3f-aa70-2c4d925858e2', 'zoom-out', '74b90980-372a-4244-b0f5-4eff1808bc09', '闪现', 'Zoom Out', 'ひらめきます', '閃現', '2024-08-16 06:35:26.564', '2024-08-16 06:35:26.564');
+INSERT INTO "public"."Internalization" VALUES ('38e2d11e-6cca-4334-ba0d-f69ed005f410', 'none', '74b90980-372a-4244-b0f5-4eff1808bc09', '无', 'None', 'ありません', '無', '2024-08-16 06:35:51.191', '2024-08-16 06:35:51.191');
+INSERT INTO "public"."Internalization" VALUES ('77edff4a-c81c-4cf8-b7e8-bd2d056399b9', 'fixedHeaderAndTab', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', '固定头部和标签栏', 'Fixed header and TAB bar', '頭とタグバーを固定します', '固定頭部和標簽欄', '2024-08-16 06:36:44.948', '2024-08-16 06:36:44.948');
+INSERT INTO "public"."Internalization" VALUES ('ea280680-d467-4ba8-b888-535fc2bb0377', 'header', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', NULL, NULL, NULL, NULL, '2024-08-16 06:36:51.753', '2024-08-16 06:36:51.753');
+INSERT INTO "public"."Internalization" VALUES ('799ee29c-1fd4-4206-bd02-a6c0ed6b4099', 'height', 'ea280680-d467-4ba8-b888-535fc2bb0377', '头部高度', 'Head height', '頭の高さです', '頭部高度', '2024-08-16 06:37:17.3', '2024-08-16 06:37:17.3');
+INSERT INTO "public"."Internalization" VALUES ('5fffa94e-8ca2-425b-a333-0d98b2429c7b', 'breadcrumb', 'ea280680-d467-4ba8-b888-535fc2bb0377', NULL, NULL, NULL, NULL, '2024-08-16 06:37:24.226', '2024-08-16 06:37:24.226');
+INSERT INTO "public"."Internalization" VALUES ('9076992e-b031-4a15-b3dd-224412c14923', 'visible', '5fffa94e-8ca2-425b-a333-0d98b2429c7b', '显示面包屑', 'Show crumbs', 'パンくずが表示されます', '顯示面包屑', '2024-08-16 06:37:53.006', '2024-08-16 06:37:53.006');
+INSERT INTO "public"."Internalization" VALUES ('7f1e1b3a-89c5-4e5c-8fba-f4eb116e5420', 'showIcon', '5fffa94e-8ca2-425b-a333-0d98b2429c7b', '显示面包屑图标', 'The breadcrumb icon is displayed', 'パン屑のアイコンが表示されます', '顯示面包屑圖標', '2024-08-16 06:38:20.858', '2024-08-16 06:38:20.858');
+INSERT INTO "public"."Internalization" VALUES ('a95c3f50-c44e-4da6-a3f9-943aa40364e4', 'tab', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', NULL, NULL, NULL, NULL, '2024-08-16 06:38:33.525', '2024-08-16 06:38:33.525');
+INSERT INTO "public"."Internalization" VALUES ('22a9eefc-00d7-4847-9a58-d0e5477b279b', 'visible', 'a95c3f50-c44e-4da6-a3f9-943aa40364e4', '显示标签栏', 'Show TAB bar', 'タブバーを表示します', '顯示標簽欄', '2024-08-16 06:38:57.28', '2024-08-16 06:38:57.28');
+INSERT INTO "public"."Internalization" VALUES ('46e2d862-e85e-4183-912b-26e3d3c84d04', 'cache', 'a95c3f50-c44e-4da6-a3f9-943aa40364e4', '缓存标签页', 'Cache TAB', 'キャッシュタブです', '緩存標簽頁', '2024-08-16 06:39:27.126', '2024-08-16 06:39:27.126');
+INSERT INTO "public"."Internalization" VALUES ('e1c0212b-55d6-4d1e-a625-17a4379099af', 'height', 'a95c3f50-c44e-4da6-a3f9-943aa40364e4', '标签栏高度', 'Label field height', 'タグバーの高さです', '標簽欄高度', '2024-08-16 06:39:54.479', '2024-08-16 06:39:54.479');
+INSERT INTO "public"."Internalization" VALUES ('2db7a969-95f7-4c3b-8b10-249948540de6', 'mode', 'a95c3f50-c44e-4da6-a3f9-943aa40364e4', NULL, NULL, NULL, NULL, '2024-08-16 06:40:02.927', '2024-08-16 06:40:02.927');
+INSERT INTO "public"."Internalization" VALUES ('6a48f052-7f1b-4d66-80c9-2cb2218b1fa9', 'title', '2db7a969-95f7-4c3b-8b10-249948540de6', '标签栏风格', 'TAB bar style', 'タブバースタイルです', '標簽欄風格', '2024-08-16 06:40:28.416', '2024-08-16 06:40:28.416');
+INSERT INTO "public"."Internalization" VALUES ('09b68498-ceb7-4e10-a54b-7916acb4bb95', 'chrome', '2db7a969-95f7-4c3b-8b10-249948540de6', '谷歌风格', 'Google style', 'googleスタイルです', '谷歌風格', '2024-08-16 06:40:58', '2024-08-16 06:40:58');
+INSERT INTO "public"."Internalization" VALUES ('360f7a36-ca17-4749-9c37-4bd9427ff8ed', 'button', '2db7a969-95f7-4c3b-8b10-249948540de6', '按钮风格', 'Button style', 'ボタンスタイルです', '按鈕風格', '2024-08-16 06:41:23.263', '2024-08-16 06:41:23.263');
+INSERT INTO "public"."Internalization" VALUES ('c1fe1901-27fe-4e7a-b171-9542fe3675ca', 'inverted', 'b419c0ac-b93d-45e1-b5df-f0a672ab40af', '深色侧边栏', 'Dark sidebar', 'ダークサイドバーです', '深色側邊欄', '2024-08-16 06:42:00.524', '2024-08-16 06:42:00.524');
+INSERT INTO "public"."Internalization" VALUES ('e4143480-fb9b-41ac-9fdb-f064543dc3b8', 'width', 'b419c0ac-b93d-45e1-b5df-f0a672ab40af', '侧边栏宽度', 'Sidebar width', 'サイドバーの幅です', '側邊欄寬度', '2024-08-16 06:42:28.261', '2024-08-16 06:42:28.261');
+INSERT INTO "public"."Internalization" VALUES ('cc4b6c8e-ac89-4be4-9d1b-24ef4316a937', 'mixWidth', 'b419c0ac-b93d-45e1-b5df-f0a672ab40af', '混合布局侧边栏宽度', 'Mix layout sidebar widths', 'ハイブリッドレイアウトサイドバー幅', '混合布局側邊欄寬度', '2024-08-16 06:43:20.248', '2024-08-16 06:43:20.248');
+INSERT INTO "public"."Internalization" VALUES ('e470bb89-fe65-424c-a1a8-aba2c47443b2', 'mixCollapsedWidth', 'b419c0ac-b93d-45e1-b5df-f0a672ab40af', '混合布局侧边栏折叠宽度', 'Mix layout sidebar fold widths', 'ハイブリッドレイアウトサイドバー折りたたみ幅', '混合布局側邊欄折疊寬度', '2024-08-16 06:43:46.9', '2024-08-16 06:43:46.9');
+INSERT INTO "public"."Internalization" VALUES ('e108b376-56a8-44ee-9b19-189538070a2b', 'mixChildMenuWidth', 'b419c0ac-b93d-45e1-b5df-f0a672ab40af', '混合布局子菜单宽度', 'Mix layout submenu widths', 'ハイブリッドレイアウトサブメニュー幅です', '混合布局子菜單寬度', '2024-08-16 06:44:20.735', '2024-08-16 06:44:20.735');
+INSERT INTO "public"."Internalization" VALUES ('7a073af1-a3ba-4307-9b56-5c41403a917d', 'footer', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', NULL, NULL, NULL, NULL, '2024-08-16 06:44:27.336', '2024-08-16 06:44:27.336');
+INSERT INTO "public"."Internalization" VALUES ('6d3c11e3-3f5b-42ee-8b94-87321f7fd20b', 'visible', '7a073af1-a3ba-4307-9b56-5c41403a917d', '显示底部', 'Display bottom', '下部を示します', '顯示底部', '2024-08-16 06:44:53.203', '2024-08-16 06:44:53.203');
+INSERT INTO "public"."Internalization" VALUES ('778aaa52-0d47-419a-b0af-381f5f4a5ac7', 'pageFunTitle', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', '页面功能', 'Page function', 'ページ機能です', '頁面功能', '2024-08-16 06:47:14.533', '2024-08-16 06:47:14.533');
+INSERT INTO "public"."Internalization" VALUES ('60d5bc21-9442-4101-a74b-b3701fa62012', 'configOperation', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', NULL, NULL, NULL, NULL, '2024-08-16 06:47:22.067', '2024-08-16 06:47:22.067');
+INSERT INTO "public"."Internalization" VALUES ('bc6594dd-e94f-4a64-9783-717b3f60bb77', 'resetConfig', '60d5bc21-9442-4101-a74b-b3701fa62012', '重置配置', 'Reset configuration', 'リセット構成です', '重置配置', '2024-08-16 06:48:42.843', '2024-08-16 06:48:42.843');
+INSERT INTO "public"."Internalization" VALUES ('d0509c27-90ef-4cf8-999d-045460aff9c2', 'resetSuccessMsg', '60d5bc21-9442-4101-a74b-b3701fa62012', '重置成功', 'Reset successfully', 'リセット成功です', '重置成功', '2024-08-16 06:49:08.855', '2024-08-16 06:49:08.855');
+INSERT INTO "public"."Internalization" VALUES ('dd4a69ce-2c87-40a2-8588-5f9108f8615b', 'collapsedWidth', 'b419c0ac-b93d-45e1-b5df-f0a672ab40af', '侧边栏折叠宽度', 'Sidebar fold width', 'サイドバー折りたたみ幅', '側邊欄折疊寬度', '2024-08-16 06:42:55.303', '2024-08-16 06:42:55.303');
+INSERT INTO "public"."Internalization" VALUES ('98a437c8-7e54-45fe-bb45-a41b33018bd1', 'fixed', '7a073af1-a3ba-4307-9b56-5c41403a917d', '固定底部', 'Fixed bottom', '底を固定します', '固定底部', '2024-08-16 06:45:20.168', '2024-08-16 06:45:20.168');
+INSERT INTO "public"."Internalization" VALUES ('59c9ceab-1fa4-489b-a0b0-f1a89d40689f', 'height', '7a073af1-a3ba-4307-9b56-5c41403a917d', '底部高度', 'Bottom height', '底の高さです', '底部高度', '2024-08-16 06:45:43.203', '2024-08-16 06:45:43.203');
+INSERT INTO "public"."Internalization" VALUES ('98f5e883-8643-4123-b853-90e3b7911339', 'right', '7a073af1-a3ba-4307-9b56-5c41403a917d', '底部局右', 'Bottom right', '下の局右です', '底部局右', '2024-08-16 06:46:06.707', '2024-08-16 06:46:06.707');
+INSERT INTO "public"."Internalization" VALUES ('0c673654-a15a-496d-a25c-b2ab9cd8d8ab', 'themeDrawerTitle', 'f3884914-186c-4e1c-9cb1-a6628383f0ef', '主题配置', 'Topic configuration', 'テーマ配置です', '主題配置', '2024-08-16 06:46:32.501', '2024-08-16 06:46:32.501');
+INSERT INTO "public"."Internalization" VALUES ('90450617-95fd-4a79-b552-22487b89e7be', 'copyConfig', '60d5bc21-9442-4101-a74b-b3701fa62012', '复制配置', 'Copy configuration', '複製構成です', '復製配置', '2024-08-16 06:47:48.696', '2024-08-16 06:47:48.696');
+INSERT INTO "public"."Internalization" VALUES ('e645bfcd-87b3-4eb8-a11b-7d8963a2efc5', 'copySuccessMsg', '60d5bc21-9442-4101-a74b-b3701fa62012', '复制成功,请替换 src/theme/settings.ts 中的变量 themeSettings', 'Copy successfully, replace themeSettings variable in src/theme/settings.ts', 'コピーに成功し、src/theme/settings.tsの変数themeSettingsを置き換えてください', '復製成功,請替換 src/theme/settings.ts 中的變量 themeSettings', '2024-08-16 06:48:17.007', '2024-08-16 06:48:17.007');
+INSERT INTO "public"."Internalization" VALUES ('f172c382-55ab-45e9-85ca-51622e42561d', 'title', '54d1a5bd-0275-4a27-a613-63f679a50d4d', 'Vue3 Admin', 'Vue3 Admin', 'Vue3 Admin', 'Vue3 Admin', '2024-08-15 02:58:04.051', '2024-08-16 07:38:54.144');
+INSERT INTO "public"."Internalization" VALUES ('e3f70933-59ad-4504-9a51-03067aa1e484', 'introduction', '9eac8021-68e5-4458-962e-a9dbb92cd842', 'Vue3 Admin 是一个基于 Nest.js 全栈开发的后台管理系统,前台在 SoybeanAdmin 的基础上二次开发,完成了常规后台项目的功能,开箱即用,非常适合新手开发者学习借鉴。', 'Vue3 Admin is a background management system based on Nest.js full stack development, the foreground in SoybeanAdmin on the basis of secondary development, completed the functions of the regular background project, out of the box, very suitable for novice developers to learn from', 'Vue3 Adminはnest.jsのフルスタックに基づいて開発されたバックグランド管理システムです。フロントはSoybeanAdminの基礎の上で二次開発して、通常のバックグランドプロジェクトの機能を完成しました', 'Vue3 Admin 是一個基於 Nest.js 全棧開發的後臺管理系統,前臺在 SoybeanAdmin 的基礎上二次開發,完成了常規後臺項目的功能,開箱即用,非常適合新手開發者學習借鑒。', '2024-08-15 10:15:38.933', '2024-08-16 07:59:52.864');
+INSERT INTO "public"."Internalization" VALUES ('202b8817-e96b-48fc-9ecc-11b4b9d1982c', 'system-manage_menu-manage', '87f643e2-de02-41b2-bc4b-867273fe0295', '菜单管理', 'Menu Manage', 'メニュー管理です', '菜單管理', '2024-08-19 01:26:45.053', '2024-08-19 01:26:45.053');
+INSERT INTO "public"."Internalization" VALUES ('ea4bb44e-7698-4638-ba7a-185e727a9d8e', 'menuManage', 'c722a9a1-2d00-4281-9155-c7b2845080f2', NULL, NULL, NULL, NULL, '2024-08-19 03:11:16.702', '2024-08-19 03:11:16.702');
+INSERT INTO "public"."Internalization" VALUES ('3e22ffb8-a118-47f0-b744-a7e48e233bd1', 'addMenu', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', '新增菜单', 'Add Menu', 'メニュー追加です', '新增菜單', '2024-08-19 03:12:29.485', '2024-08-19 03:12:29.485');
+INSERT INTO "public"."Internalization" VALUES ('34a6434c-0bed-4be7-a82c-fa20dd1afafa', 'editMenu', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', '编辑菜单', 'Edit Menu', 'メニューを編集します', '編輯菜單', '2024-08-19 03:13:08.392', '2024-08-19 03:13:08.392');
+INSERT INTO "public"."Internalization" VALUES ('6bcdb650-529a-4081-b286-133bd7761293', 'type', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', '菜单类型', 'Menu Type', 'メニュータイプです', '菜單類型', '2024-08-19 09:21:31.475', '2024-08-19 09:21:31.475');
+INSERT INTO "public"."Internalization" VALUES ('1a943c5f-5e53-4557-899b-bae911bfe7e2', 'title', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', '菜单名称', 'Menu Name', 'メニュー名です', '菜單名稱', '2024-08-19 09:22:05.318', '2024-08-19 09:22:05.318');
+INSERT INTO "public"."Internalization" VALUES ('07449d4c-dd91-484e-b0c5-e4856de6d337', 'name', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', '路由名称', 'Route Name', 'ルート名です', '路由名稱', '2024-08-19 09:23:19.933', '2024-08-19 09:23:19.933');
+INSERT INTO "public"."Internalization" VALUES ('6855613a-868d-4bca-840c-ce42794e20d4', 'path', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', '路由路径', 'Route Path', '経路を指定します', '路由路徑', '2024-08-19 09:23:52.708', '2024-08-19 09:23:52.708');
+INSERT INTO "public"."Internalization" VALUES ('30e08c04-51a8-47b5-a73c-08082d16a6e5', 'component', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', '组件', 'Component', 'コンポーネントです', '組件', '2024-08-19 09:24:36.964', '2024-08-19 09:24:36.964');
+INSERT INTO "public"."Internalization" VALUES ('c15497dd-9a3c-4ac5-a95f-88c52d543450', 'href', '1f8c06d4-8a9e-49bf-b75b-cbbb9e8c1e39', '外链', 'Href', '外鎖です', '外鏈', '2024-08-20 02:02:24.747', '2024-08-20 02:02:24.747');
+INSERT INTO "public"."Internalization" VALUES ('d453e11d-4fa1-41bc-8813-3b93dbb25558', 'typeMap', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', NULL, NULL, NULL, NULL, '2024-08-19 09:38:04.939', '2024-08-19 09:38:04.939');
+INSERT INTO "public"."Internalization" VALUES ('ead407ef-3edd-4ad2-9aa5-8917f8c098f7', 'directory', 'd453e11d-4fa1-41bc-8813-3b93dbb25558', '目录', 'Directory', '目次', '目錄', '2024-08-19 09:37:30.321', '2024-08-19 09:38:09.615');
+INSERT INTO "public"."Internalization" VALUES ('1c9e9753-849b-4a8f-9e45-f29f6826d2f8', 'menu', 'd453e11d-4fa1-41bc-8813-3b93dbb25558', '菜单', 'Menu', 'メニューです', '菜單', '2024-08-19 09:38:35.179', '2024-08-19 09:38:35.179');
+INSERT INTO "public"."Internalization" VALUES ('e7ab9ff7-b8c2-4ec5-95e0-9431110403d8', 'button', 'd453e11d-4fa1-41bc-8813-3b93dbb25558', '按钮', 'Button', 'ボタンです', '按鈕', '2024-08-19 09:39:02.997', '2024-08-19 09:39:02.997');
+INSERT INTO "public"."Internalization" VALUES ('1f8c06d4-8a9e-49bf-b75b-cbbb9e8c1e39', 'meta', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', NULL, NULL, NULL, NULL, '2024-08-19 09:48:10.84', '2024-08-19 09:48:10.84');
+INSERT INTO "public"."Internalization" VALUES ('73d035ec-47f3-4777-9027-0d9ae1c060f3', 'icon', '1f8c06d4-8a9e-49bf-b75b-cbbb9e8c1e39', '图标', 'Icon', 'アイコンです', '圖標', '2024-08-19 09:22:47.858', '2024-08-19 09:48:22.06');
+INSERT INTO "public"."Internalization" VALUES ('c3b56fe9-38ce-40c7-a4da-4a0005b586b5', 'permission', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', '权限标识', 'Permission identification', '権限表示です', '權限標識', '2024-08-20 01:43:26.237', '2024-08-20 01:43:26.237');
+INSERT INTO "public"."Internalization" VALUES ('2baa70f0-3c77-4f76-b89c-7660e5ad8585', 'routeMeta', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', '路由元信息', 'Route Meta', 'ルーティングメタ情報です', '路由元信息', '2024-08-20 01:49:24.299', '2024-08-20 01:49:24.299');
+INSERT INTO "public"."Internalization" VALUES ('603e2d06-c045-43a3-8e8d-e695a7fc2d9b', 'title', '1f8c06d4-8a9e-49bf-b75b-cbbb9e8c1e39', '路由标题', 'Route Title', 'ルーティングタイトルです', '路由標題', '2024-08-20 01:55:39.932', '2024-08-20 01:55:39.932');
+INSERT INTO "public"."Internalization" VALUES ('488bafff-d633-42f8-99b3-5bd6bc8a72d3', 'i18nKey', '1f8c06d4-8a9e-49bf-b75b-cbbb9e8c1e39', '国际化key', 'Internationalization key', 'グローバルkeyです', '國際化key', '2024-08-20 01:56:37.963', '2024-08-20 01:56:37.963');
+INSERT INTO "public"."Internalization" VALUES ('84fb15db-00ca-4466-844a-5beb7a236a82', 'keepAlive', '1f8c06d4-8a9e-49bf-b75b-cbbb9e8c1e39', '缓存路由', 'Cache routing', 'キャッシュ・ルーティング', '緩存路由', '2024-08-20 01:57:58.61', '2024-08-20 01:57:58.61');
+INSERT INTO "public"."Internalization" VALUES ('dfe2e5bd-745c-4b62-9eb4-e28678b9df73', 'constant', '1f8c06d4-8a9e-49bf-b75b-cbbb9e8c1e39', '常量路由', 'Constant routing', '定数経路', '常量路由', '2024-08-20 01:59:42.699', '2024-08-20 01:59:42.699');
+INSERT INTO "public"."Internalization" VALUES ('1c548796-24e2-42d6-a545-35d6e471c4e7', 'order', '1f8c06d4-8a9e-49bf-b75b-cbbb9e8c1e39', '路由排序', 'Route sorting', '順序付けです', '路由排序', '2024-08-20 02:01:34.149', '2024-08-20 02:01:34.149');
+INSERT INTO "public"."Internalization" VALUES ('1c20ba7b-2e74-4b64-9a83-15b87169347a', 'hideInMenu', '1f8c06d4-8a9e-49bf-b75b-cbbb9e8c1e39', '隐藏路由', 'Hidden route', '隠しルートです', '隱藏路由', '2024-08-20 02:03:07.38', '2024-08-20 02:03:07.38');
+INSERT INTO "public"."Internalization" VALUES ('acc30842-c98c-4592-8a3e-989f400e3b56', 'multiTab', '1f8c06d4-8a9e-49bf-b75b-cbbb9e8c1e39', '多页签', 'multi-tab', '何枚かのくじです', '多頁簽', '2024-08-20 02:04:35.016', '2024-08-20 02:04:35.016');
+INSERT INTO "public"."Internalization" VALUES ('ba867dab-562d-4983-9bf7-e07315309389', 'fixedIndexInTab', '1f8c06d4-8a9e-49bf-b75b-cbbb9e8c1e39', '固定页签序号', 'Fixed TAB number', 'ページ番号を固定します', '固定頁簽序號', '2024-08-20 02:05:41.181', '2024-08-20 02:05:41.181');
+INSERT INTO "public"."Internalization" VALUES ('1dc06aff-fc1e-4caf-91f1-a13bf88ebe3a', 'yesOrNo', '5892893b-70fb-4e2d-9ea8-0793bc48fd5d', NULL, NULL, NULL, NULL, '2024-08-20 03:18:48.24', '2024-08-20 03:18:48.24');
+INSERT INTO "public"."Internalization" VALUES ('9d34d887-7333-4dbb-81fa-8b45cd3403e9', 'system-manage_role-manage', '87f643e2-de02-41b2-bc4b-867273fe0295', '角色管理', 'Role Manage', '役割管理です', '角色管理', '2024-08-22 08:32:59.489', '2024-08-22 08:32:59.489');
+INSERT INTO "public"."Internalization" VALUES ('52c6323b-3d27-4042-a4e2-104a6f9fad04', 'roleManage', 'c722a9a1-2d00-4281-9155-c7b2845080f2', NULL, NULL, NULL, NULL, '2024-08-22 08:48:39.682', '2024-08-22 08:48:39.682');
+INSERT INTO "public"."Internalization" VALUES ('04c6d895-9394-4bba-a0eb-46d46328e448', 'name', '52c6323b-3d27-4042-a4e2-104a6f9fad04', '角色名称', 'Role Name', '役名です', '角色名稱', '2024-08-22 08:49:18.782', '2024-08-22 08:49:18.782');
+INSERT INTO "public"."Internalization" VALUES ('2e15e985-1626-4c66-9344-61f2fa7417b3', 'code', '52c6323b-3d27-4042-a4e2-104a6f9fad04', '角色编码', 'Role Code', 'キャラクターコードです', '角色编码', '2024-08-22 08:49:49.896', '2024-08-22 08:49:49.896');
+INSERT INTO "public"."Internalization" VALUES ('5d8525b6-bc72-414a-88c9-6e748ced4eef', 'description', '52c6323b-3d27-4042-a4e2-104a6f9fad04', '角色描述', 'Description', 'キャラクター描写です', '角色描述', '2024-08-22 08:50:55.61', '2024-08-22 08:50:55.61');
+INSERT INTO "public"."Internalization" VALUES ('426ef093-39e3-4608-8e9a-37348edd8ad1', 'addRole', '52c6323b-3d27-4042-a4e2-104a6f9fad04', '添加角色', 'Add Role', 'キャラクターを追加します', '添加角色', '2024-08-22 08:51:40.538', '2024-08-22 08:51:40.538');
+INSERT INTO "public"."Internalization" VALUES ('3ca80ec2-f4da-4ba8-977a-bb70107fdc4b', 'editRole', '52c6323b-3d27-4042-a4e2-104a6f9fad04', '编辑角色', 'Edit Role', '編集役です', '編輯角色', '2024-08-22 08:52:14.003', '2024-08-22 08:52:14.003');
+INSERT INTO "public"."Internalization" VALUES ('98c9d248-6b50-419e-8f7a-b4a7dfe855e8', 'menus', '52c6323b-3d27-4042-a4e2-104a6f9fad04', '菜单权限', 'Menu permissions', 'メニュー権限です', '菜單權限', '2024-08-22 08:53:03.677', '2024-08-22 08:53:03.677');
+INSERT INTO "public"."Internalization" VALUES ('7a58785e-9412-4e6e-9786-64d9f3dbde69', 'roleId', '598aa0c9-2176-45e1-a66f-bea42863b03f', '所属角色', 'Role', '所属しています', '所屬角色', '2024-08-23 02:48:19.725', '2024-08-23 02:48:19.725');
+INSERT INTO "public"."Internalization" VALUES ('07174026-7171-4c96-ab68-3f1e9c340ba5', 'userCenter', '1df58855-e0e0-4b79-b321-b45b8b3afebd', NULL, NULL, NULL, NULL, '2024-08-26 06:10:50.682', '2024-08-26 06:10:50.682');
+INSERT INTO "public"."Internalization" VALUES ('6102d56d-dbb6-4cbd-a52e-f8d5f1a45b84', 'title', '07174026-7171-4c96-ab68-3f1e9c340ba5', NULL, NULL, NULL, NULL, '2024-08-26 08:46:20.602', '2024-08-26 08:46:20.602');
+INSERT INTO "public"."Internalization" VALUES ('3c8f97bf-6bcc-4ff3-a290-6653deeec862', 'securitySetting', '6102d56d-dbb6-4cbd-a52e-f8d5f1a45b84', '安全设置', 'Security Settings', 'セキュリティ設定です', '安全設置', '2024-08-26 07:52:42.941', '2024-08-26 08:46:26.276');
+INSERT INTO "public"."Internalization" VALUES ('062070be-1be8-4e08-8409-318c00e67c06', 'basicSetting', '6102d56d-dbb6-4cbd-a52e-f8d5f1a45b84', '基本设置', 'Basic Setting', '基本設定です', '基本設置', '2024-08-26 06:11:48.838', '2024-08-26 08:46:31.13');
+INSERT INTO "public"."Internalization" VALUES ('96d53a21-6779-46a9-aed5-88e39f69b7c7', 'securitySetting', '07174026-7171-4c96-ab68-3f1e9c340ba5', NULL, NULL, NULL, NULL, '2024-08-26 08:46:40.057', '2024-08-26 08:46:40.057');
+INSERT INTO "public"."Internalization" VALUES ('7ba47dd7-dcf9-4c27-b2d2-04e25b292372', 'authentication', '96d53a21-6779-46a9-aed5-88e39f69b7c7', '实名认证', 'Authentication', '実名認証です', '實名認證', '2024-08-26 08:48:08.121', '2024-08-26 08:48:08.121');
+INSERT INTO "public"."Internalization" VALUES ('50a6be79-5c55-4663-8f27-3a07b6d467cf', 'authentication-information', '96d53a21-6779-46a9-aed5-88e39f69b7c7', '认证信息:{cnName}', 'Authentication Information:{cnName}', '認証情報です:{cnName}', '認證信息:{cnName}', '2024-08-26 08:51:09.781', '2024-08-26 08:51:09.781');
+INSERT INTO "public"."Internalization" VALUES ('89f3bcf1-3594-4ed8-bc87-8e5cb581e32c', 'account-password', '96d53a21-6779-46a9-aed5-88e39f69b7c7', '账户密码', 'Account password', '口座番号です', '賬戶密碼', '2024-08-26 08:52:16.43', '2024-08-26 08:52:16.43');
+INSERT INTO "public"."Internalization" VALUES ('f791473c-b99c-41c5-99de-6e9c626933a9', 'account-password-desc', '96d53a21-6779-46a9-aed5-88e39f69b7c7', '已设置,密码6-18位字符,支持数字、字母和除空格外的特殊字符,且必须同时包含数字和小写字母。', 'Yes, the password is a string of 6 to 18 characters, including digits, letters, and special characters except Spaces, and must contain lowercase letters and digits at the same time.', 'パスワードは6-18桁で、数字、アルファベット、スペースを除く特殊な文字をサポートし、数字と小文字の両方を含む必要があります。', '已設置,密碼6-18位字符,支持數字、字母和除空格外的特殊字符,且必須同時包含數字和小寫字母。', '2024-08-26 08:53:10.82', '2024-08-26 08:53:10.82');
+INSERT INTO "public"."Internalization" VALUES ('28f5b144-2393-4974-89eb-77453241db8b', 'security-phone', '96d53a21-6779-46a9-aed5-88e39f69b7c7', '密保手机', 'Security phone', 'セキュリティー携帯です', '密保手機', '2024-08-26 08:54:29.124', '2024-08-26 08:54:29.124');
+INSERT INTO "public"."Internalization" VALUES ('cdafdad0-a625-4035-aa8a-01e2f970aace', 'security-phone-desc', '96d53a21-6779-46a9-aed5-88e39f69b7c7', '已绑定手机:{phone}', 'Bound mobile phone: {phone}', '携帯電話に紐付けました:{phone}', '已綁定手機:{phone}', '2024-08-26 08:56:19.989', '2024-08-26 08:56:19.989');
+INSERT INTO "public"."Internalization" VALUES ('d017938d-92e7-41fd-8e10-8105159aca53', 'security-email', '96d53a21-6779-46a9-aed5-88e39f69b7c7', '安全邮箱', 'Security email', '安全メールボックスです', '安全郵箱', '2024-08-26 08:57:40.977', '2024-08-26 08:57:40.977');
+INSERT INTO "public"."Internalization" VALUES ('fb1ce5d6-0195-46d0-b87e-a19631f3c3af', 'security-email-desc', '96d53a21-6779-46a9-aed5-88e39f69b7c7', '已绑定邮箱:{email}', 'Bound email address: {email}', 'メールボックスにバインディング済みです:{email}', '已綁定郵箱:{email}', '2024-08-26 08:58:49.634', '2024-08-26 08:58:49.634');
+INSERT INTO "public"."Internalization" VALUES ('85733586-b1ab-463a-9a72-42697c07d80c', 'authenticated', '96d53a21-6779-46a9-aed5-88e39f69b7c7', '已认证', 'Authenticated', '認証済みです', '已認證', '2024-08-26 09:01:47.405', '2024-08-26 09:01:47.405');
+INSERT INTO "public"."Internalization" VALUES ('3a27846b-532a-40a9-a0cf-fec16b173d06', 'changePassword', '6102d56d-dbb6-4cbd-a52e-f8d5f1a45b84', '修改密码', 'Change Password', 'パスワードを変更します', '修改密碼', '2024-08-27 02:04:34.608', '2024-08-27 02:04:34.608');
+INSERT INTO "public"."Internalization" VALUES ('9e96fd60-3701-4897-a1e1-e1cc7928fc8d', 'password', '598aa0c9-2176-45e1-a66f-bea42863b03f', '密码', 'Password', 'パスワードです', '密碼', '2024-08-16 01:51:17.166', '2024-08-27 02:19:43.525');
+INSERT INTO "public"."Internalization" VALUES ('9383c777-c449-4dc3-8211-e63ef964d081', 'oldPwd', '2b85664c-ea80-4401-981a-e93ad807d983', NULL, NULL, NULL, NULL, '2024-08-27 02:53:03.648', '2024-08-27 02:53:03.648');
+INSERT INTO "public"."Internalization" VALUES ('8db054ab-898f-4a45-9fc7-c225b3435887', 'required', '9383c777-c449-4dc3-8211-e63ef964d081', '请输入原密码', 'Please enter the old password', '元のパスワードをお願いします', '請輸入原密碼', '2024-08-27 02:53:42.907', '2024-08-27 02:53:42.907');
+INSERT INTO "public"."Internalization" VALUES ('0972d59d-d793-4be0-a630-a989a3239c54', 'invalid', '9383c777-c449-4dc3-8211-e63ef964d081', '原密码格式不正确,6-18位字符,包含字母、数字、下划线', 'The format of the old password is incorrect. The password contains 6 to 18 characters, including letters, digits, and underscores', '元の暗号形式は正しくありません、6-18桁文字、アルファベット、数字、下線を含みます', '原密碼格式不正確,6-18位字符,包含字母、數字、下劃線', '2024-08-27 02:55:05.949', '2024-08-27 02:55:05.949');
+INSERT INTO "public"."Internalization" VALUES ('42f81c2a-063b-4b77-a50b-7396b2c3c5d8', 'label', '9383c777-c449-4dc3-8211-e63ef964d081', '原密码', 'Old password', '元のパスワードです', '原密碼', '2024-08-27 02:49:09.751', '2024-08-27 02:59:02.361');
+INSERT INTO "public"."Internalization" VALUES ('f529b629-5ded-415e-ac63-d47dafa1b17c', 'loginNow', 'ea1839ad-c98f-49eb-a6c3-12ad1ac7a37a', '立刻登录', 'Log in now', 'すぐにログインします', '立刻登錄', '2024-08-28 06:43:03.958', '2024-08-28 06:43:03.958');
+INSERT INTO "public"."Internalization" VALUES ('80ac3ae9-c800-461c-8df5-ddcd1ee4573f', 'message', 'be1235ea-a62d-4c17-9932-bc42e26a58be', '', '', '', '', '2024-09-02 08:41:45.022', '2024-09-02 08:41:45.022');
+INSERT INTO "public"."Internalization" VALUES ('b118a6b7-7a43-47ce-a80d-2f4c2435e757', 'title', '80ac3ae9-c800-461c-8df5-ddcd1ee4573f', '标题', 'Title', '見出しです', '標題', '2024-09-02 08:42:36.561', '2024-09-02 08:42:36.561');
+INSERT INTO "public"."Internalization" VALUES ('260af93e-a72d-40cb-b15c-f9cd607c502a', 'userId', '80ac3ae9-c800-461c-8df5-ddcd1ee4573f', '作者', 'Author', '作者です', '作者', '2024-09-02 08:43:13.27', '2024-09-02 08:43:13.27');
+INSERT INTO "public"."Internalization" VALUES ('166d3c36-40bf-4d47-9334-5d61b7327b91', 'administrative_message', '87f643e2-de02-41b2-bc4b-867273fe0295', '消息公告', 'News announcement', 'お知らせします', '消息公告', '2024-09-02 08:40:29.632', '2024-09-02 08:40:29.632');
+INSERT INTO "public"."Internalization" VALUES ('4926d534-6cfd-4bc5-9f01-eecf8d59fdd4', 'pinned', '80ac3ae9-c800-461c-8df5-ddcd1ee4573f', '是否置顶', 'Pinned', '屋根ですか', '是否置頂', '2024-09-02 08:44:13.351', '2024-09-02 08:44:13.351');
+INSERT INTO "public"."Internalization" VALUES ('b49fdd84-d4c4-4674-8252-d7f8f4770e8b', 'addMessage', '80ac3ae9-c800-461c-8df5-ddcd1ee4573f', '新增消息公告', 'New message announcement', 'お知らせを追加します', '新增消息公告', '2024-09-02 09:12:09.548', '2024-09-02 09:12:09.548');
+INSERT INTO "public"."Internalization" VALUES ('a40f1852-5a74-4f91-b905-36b760a58085', 'administrative_framework', '87f643e2-de02-41b2-bc4b-867273fe0295', '组织架构', 'Organizational structure', '組織構造です', '組織架構', '2024-09-14 03:37:44.711', '2024-09-14 03:37:44.711');
+INSERT INTO "public"."Internalization" VALUES ('f659c553-4662-4864-9d95-c50ea6f50bdb', 'editMessage', '80ac3ae9-c800-461c-8df5-ddcd1ee4573f', '编辑消息公告', 'Edit message announcement', 'ニュースを編集してお知らせします', '編輯消息公告', '2024-09-02 09:13:35.209', '2024-09-02 09:13:35.209');
+INSERT INTO "public"."Internalization" VALUES ('3e9d3520-1384-4f25-a923-0868266129fd', 'content', '80ac3ae9-c800-461c-8df5-ddcd1ee4573f', '内容', 'Content', '中身です', '內容', '2024-09-02 09:46:49.635', '2024-09-02 09:46:49.635');
+INSERT INTO "public"."Internalization" VALUES ('4bb8f23f-9494-405e-9233-656a0d54a800', 'administrative_message-detail', '87f643e2-de02-41b2-bc4b-867273fe0295', '消息公告详情', 'News Announcement Details', '情報は詳細を公告します', '消息公告詳情', '2024-09-03 09:54:50.671', '2024-09-03 09:55:58.247');
+INSERT INTO "public"."Internalization" VALUES ('71337983-5966-4ac1-8f00-593ff824c52b', 'read', '80ac3ae9-c800-461c-8df5-ddcd1ee4573f', '已读', 'Read', '既読です', '已讀', '2024-09-04 02:21:54.048', '2024-09-04 02:21:54.048');
+INSERT INTO "public"."Internalization" VALUES ('28ee38bd-7d87-401e-bdb2-71c801abc326', 'button', '0ae5a043-07b4-4943-935d-1e0996423a65', '选择图片', 'Select picture', '画像を選択します', '選擇圖片', '2024-09-04 09:50:41.48', '2024-09-04 09:50:41.48');
+INSERT INTO "public"."Internalization" VALUES ('a11e4c8e-e766-4a87-8ff3-1b3b71429ee9', 'publishMessage', '6102d56d-dbb6-4cbd-a52e-f8d5f1a45b84', '已发布消息公告', 'Publish Message', '発表メッセージ', '已發布消息公告', '2024-09-05 03:24:35.131', '2024-09-05 03:24:35.131');
+INSERT INTO "public"."Internalization" VALUES ('513d4886-8ad5-4e10-b5f0-88d72e60246e', 'notificationButton', '4755ce71-0f46-4c57-87bc-2556516871bb', '', '', '', '', '2024-09-09 06:22:08.691', '2024-09-09 06:22:08.691');
+INSERT INTO "public"."Internalization" VALUES ('6e29da90-0841-4791-a111-d5d9cff6a503', 'title', '513d4886-8ad5-4e10-b5f0-88d72e60246e', '发布了一条新消息', 'A new message was posted', '新しいニュースを発表しました', '發布了一條新消息', '2024-09-09 06:25:21.639', '2024-09-09 06:25:21.639');
+INSERT INTO "public"."Internalization" VALUES ('1c8d5d95-6df8-4576-8d37-cfd260c7e84e', 'view', '513d4886-8ad5-4e10-b5f0-88d72e60246e', '立即查看', 'View now', 'すぐに調べます', '立即查看', '2024-09-09 06:25:57.754', '2024-09-09 06:25:57.754');
+INSERT INTO "public"."Internalization" VALUES ('1b165329-1493-4d7f-8dfe-7dbcea346579', 'document', '87f643e2-de02-41b2-bc4b-867273fe0295', '技术文档', 'Technical document', '技術文書です', '技術文檔', '2024-09-09 08:36:17.531', '2024-09-09 08:36:17.531');
+INSERT INTO "public"."Internalization" VALUES ('4a63d2c3-f759-400f-8b7b-bd2b00a14d14', 'document_vue', '87f643e2-de02-41b2-bc4b-867273fe0295', 'Vue3', 'Vue3', 'Vue3', 'Vue3', '2024-09-09 08:36:44.843', '2024-09-09 08:36:44.843');
+INSERT INTO "public"."Internalization" VALUES ('bac0ab99-dd9d-4d8e-a844-5b2298e12502', 'document_nest', '87f643e2-de02-41b2-bc4b-867273fe0295', 'Nest.js', 'Nest.js', 'Nest.js', 'Nest.js', '2024-09-09 08:42:49.19', '2024-09-09 08:42:49.19');
+INSERT INTO "public"."Internalization" VALUES ('8a5ad04d-6b28-4d2b-ad6f-0ff97c3c4dbb', 'document_antd', '87f643e2-de02-41b2-bc4b-867273fe0295', 'Ant Design Vue', 'Ant Design Vue', 'Ant Design Vue', 'Ant Design Vue', '2024-09-09 08:43:21.324', '2024-09-09 08:43:21.324');
+INSERT INTO "public"."Internalization" VALUES ('f74a9684-5e47-43d2-b427-2ef985f711af', 'document_unocss', '87f643e2-de02-41b2-bc4b-867273fe0295', 'UnoCSS', 'UnoCSS', 'UnoCSS', 'UnoCSS', '2024-09-09 08:44:01.407', '2024-09-09 08:44:01.407');
+INSERT INTO "public"."Internalization" VALUES ('530e24a0-be2a-4e4b-bf6e-03dd19223edd', 'iframeParams', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', 'Iframe 参数', 'Iframe Params', 'Iframeパラメータです', 'Iframe 參數', '2024-09-09 09:12:37.112', '2024-09-09 09:12:37.112');
+INSERT INTO "public"."Internalization" VALUES ('e439915f-f3f8-45d5-85ed-406b45fd67b3', 'props', 'ea4bb44e-7698-4638-ba7a-185e727a9d8e', '', '', '', '', '2024-09-09 09:14:18.283', '2024-09-09 09:14:18.283');
+INSERT INTO "public"."Internalization" VALUES ('c20a83f4-df81-4af2-a679-1fa9fbdad1c5', 'url', 'e439915f-f3f8-45d5-85ed-406b45fd67b3', '内链', 'Inner chain', '内鎖です', '內鏈', '2024-09-09 09:15:00.834', '2024-09-09 09:15:00.834');
+INSERT INTO "public"."Internalization" VALUES ('de31eaa5-1960-47b7-b755-4561e6a993a1', 'localIcon', '1f8c06d4-8a9e-49bf-b75b-cbbb9e8c1e39', '本地图标', 'Local Icon', 'ローカルアイコンです', '本地圖標', '2024-09-09 09:34:19.129', '2024-09-09 09:34:19.129');
+INSERT INTO "public"."Internalization" VALUES ('fee978c0-77a8-4462-8c1a-41947e41dca3', 'verifyError', 'c13f4af8-97f3-4ef7-a9a6-dff36f7310e2', '很遗憾,答案错误,请再试一次', 'Unfortunately, the answer is wrong. Please try again', '残念ですが,答えはまちがっていますので,もう一度やってください', '很遺憾,答案錯誤,請再試一次', '2024-09-10 06:59:50.76', '2024-09-10 07:47:16.299');
+INSERT INTO "public"."Internalization" VALUES ('f079b24e-8531-47d6-8dd0-baed9d9c73e9', 'document_soybean', '87f643e2-de02-41b2-bc4b-867273fe0295', 'Soybean(内链)', 'Soybean (inner chain)', 'Soybean(内鎖)です', 'Soybean(內鏈)', '2024-09-09 09:30:09.538', '2024-09-09 09:50:07.722');
+INSERT INTO "public"."Internalization" VALUES ('fdf01b75-f7d6-4607-9c13-601da225afd8', 'features', '87f643e2-de02-41b2-bc4b-867273fe0295', '功能页', 'Features', '機能ページです', '功能頁', '2024-09-10 02:29:50.749', '2024-09-10 02:29:50.749');
+INSERT INTO "public"."Internalization" VALUES ('9bad8e2d-8656-49f3-b1a3-f9020919c012', 'features_captcha', '87f643e2-de02-41b2-bc4b-867273fe0295', '验证码', 'Captcha', 'captchaコードです', '驗證碼', '2024-09-10 02:30:26.812', '2024-09-10 02:30:26.812');
+INSERT INTO "public"."Internalization" VALUES ('353a778e-3121-4593-bb58-2cbbd2136ad1', 'features', '1df58855-e0e0-4b79-b321-b45b8b3afebd', '', '', '', '', '2024-09-10 06:46:08.561', '2024-09-10 06:46:08.561');
+INSERT INTO "public"."Internalization" VALUES ('c13f4af8-97f3-4ef7-a9a6-dff36f7310e2', 'captcha', '353a778e-3121-4593-bb58-2cbbd2136ad1', '', '', '', '', '2024-09-10 06:46:30.367', '2024-09-10 06:46:30.367');
+INSERT INTO "public"."Internalization" VALUES ('b4f67e82-2809-4096-a945-45e640282674', 'graphicCode', 'c13f4af8-97f3-4ef7-a9a6-dff36f7310e2', '图形验证码', 'Graphic verification code', 'グラフィックス認証コードです', '圖形驗證碼', '2024-09-10 06:48:27.978', '2024-09-10 06:48:27.978');
+INSERT INTO "public"."Internalization" VALUES ('363a4b86-d6a5-4638-b53f-323bc945e461', 'verify', 'c13f4af8-97f3-4ef7-a9a6-dff36f7310e2', '验证', 'Verify', '検証します', '驗證', '2024-09-10 06:55:30.033', '2024-09-10 06:55:30.033');
+INSERT INTO "public"."Internalization" VALUES ('f6c58c3e-f73b-4d39-a78d-d79d96094088', 'subTitle', 'c13f4af8-97f3-4ef7-a9a6-dff36f7310e2', '验证码的主要用途是为了防止自动化程序(如机器人、爬虫等)恶意访问网站或应用程序,从而保护系统的安全性和数据的完整性,单纯前端的验证是不安全的,因为可以直接通过接口请求', 'The main purpose of captCHA is to prevent automated programs (such as robots, crawlers, etc.) from accessing websites or applications maliciously, so as to protect the security of the system and the integrity of the data. Simple front-end verification is not secure, because it can be requested directly through the interface', 'captchaの主な用途は、自動化プログラム(ロボット、クローラなど)がウェブサイトやアプリケーションに悪意を持ってアクセスするのを防ぎ、システムの安全性とデータの完全性を保護するためです。フロントエンドの検証だけでは、インターフェイス上で直接要求できるので安全ではありません', '驗證碼的主要用途是為了防止自動化程序(如機器人、爬蟲等)惡意訪問網站或應用程序,從而保護系統的安全性和數據的完整性,單純前端的驗證是不安全的,因為可以直接通過接口請求', '2024-09-10 07:15:38.675', '2024-09-10 07:15:38.675');
+INSERT INTO "public"."Internalization" VALUES ('eec0d399-e0d2-4b32-a22f-bf347634cdbf', 'verifySuccess', 'c13f4af8-97f3-4ef7-a9a6-dff36f7310e2', '恭喜您,答案正确!', 'Congratulations, the answer is correct!', 'おめでとうございます、正解です!', '恭喜您,答案正確!', '2024-09-10 06:56:50.23', '2024-09-10 07:46:31.384');
+INSERT INTO "public"."Internalization" VALUES ('e0ab158b-5577-4fc0-a537-2a4a49dd2cfe', 'operationCode', 'c13f4af8-97f3-4ef7-a9a6-dff36f7310e2', '运算验证码', 'Operational verification code', 'captchaを実行します', '運算驗證碼', '2024-09-11 01:14:12.456', '2024-09-11 01:14:12.456');
+INSERT INTO "public"."Internalization" VALUES ('50b2bd46-da66-4072-8e4c-8417ad35f0c3', 'puzzleCode', 'c13f4af8-97f3-4ef7-a9a6-dff36f7310e2', '拼图验证码', 'Puzzle Code', 'パズルcaptchaです', '拼圖驗證碼', '2024-09-11 07:27:51.067', '2024-09-11 07:27:51.067');
+INSERT INTO "public"."Internalization" VALUES ('98641d7d-affd-4f69-b64d-788098fb3eca', 'pointsCode', 'c13f4af8-97f3-4ef7-a9a6-dff36f7310e2', '点选验证码', 'Points Code', 'captchaをクリックします', '點選驗證碼', '2024-09-12 07:17:11.619', '2024-09-12 07:17:11.619');
+INSERT INTO "public"."Internalization" VALUES ('e7b7a83d-3161-49e3-b104-492c9ec2a87f', 'slideCode', 'c13f4af8-97f3-4ef7-a9a6-dff36f7310e2', '滑块验证码', 'Slide Code', 'スライダー認証コードです', '滑塊驗證碼', '2024-09-12 09:11:17.113', '2024-09-12 09:11:17.113');
+INSERT INTO "public"."Internalization" VALUES ('e443b96d-b150-42fb-b132-147ef45c9b76', 'slideCodeSuccess', 'c13f4af8-97f3-4ef7-a9a6-dff36f7310e2', '验证成功,耗时 {seconds} 秒!', 'The verification succeeds, taking {seconds} seconds!', '検証成功、{seconds}秒かかりました!', '驗證成功,耗時 {seconds} 秒!', '2024-09-13 02:52:05.028', '2024-09-13 02:52:05.028');
+INSERT INTO "public"."Internalization" VALUES ('75d84f6d-8cd6-4987-86b5-135a84b29468', 'rotateCode', 'c13f4af8-97f3-4ef7-a9a6-dff36f7310e2', '图片旋转验证码', 'Rotate Code', '画像回転認証コードです', '圖片旋轉驗證碼', '2024-09-13 06:02:32.88', '2024-09-13 06:02:32.88');
+INSERT INTO "public"."Internalization" VALUES ('fdc454f7-7703-4638-9148-cf797dd38e9e', 'features_print', '87f643e2-de02-41b2-bc4b-867273fe0295', '打印', 'Print', '印刷します', '打印', '2024-09-14 09:46:27.483', '2024-09-14 09:46:27.483');
+INSERT INTO "public"."Internalization" VALUES ('9486fb36-6395-494a-96a5-5ed2831f1a13', 'features_pickr', '87f643e2-de02-41b2-bc4b-867273fe0295', '拾色器', 'Color picker', '色拾い器です', '拾色器', '2024-09-19 01:10:06.222', '2024-09-19 01:10:06.222');
+INSERT INTO "public"."Internalization" VALUES ('fe8bf496-2629-41cf-80de-766ff93ca4c8', 'features_gantt', '87f643e2-de02-41b2-bc4b-867273fe0295', '甘特图', 'Gantt chart', 'ガントチャートです', '甘特圖', '2024-09-19 06:53:09.239', '2024-09-19 06:53:09.239');
+INSERT INTO "public"."Internalization" VALUES ('3c48456b-28fd-4f7c-8015-0dc0854ada4b', 'features_viewer', '87f643e2-de02-41b2-bc4b-867273fe0295', '图片预览', 'Image preview', 'プレビュー画像です', '圖片預覽', '2024-09-19 08:23:50.421', '2024-09-19 08:23:50.421');
+INSERT INTO "public"."Internalization" VALUES ('4538ef78-1e22-4b2f-a37e-1e624fcfd30e', 'features_vue-directive', '87f643e2-de02-41b2-bc4b-867273fe0295', '自定义 Vue 指令', 'Custom Vue Directives', 'カスタムVue命令です', '自定義 Vue 指令', '2024-09-19 10:09:50.624', '2024-09-19 10:09:50.624');
+INSERT INTO "public"."Internalization" VALUES ('94c7782d-c4b2-4886-8df5-019a48429565', 'features_lazyload', '87f643e2-de02-41b2-bc4b-867273fe0295', '懒加载', 'Lazy Load', '怠惰なロードです', '懶加載', '2024-09-20 07:22:01.068', '2024-09-20 07:22:01.068');
+INSERT INTO "public"."Internalization" VALUES ('536e9cca-c04e-40bd-ae83-596aa4b5fddd', 'features_colorthief', '87f643e2-de02-41b2-bc4b-867273fe0295', '图片取色盘', 'Picture palette', '画像パレットです', '圖片調色盤', '2024-09-20 09:21:06.557', '2024-09-20 09:21:06.557');
+INSERT INTO "public"."Internalization" VALUES ('a92aeafc-7988-408c-8721-2f3819134e6a', 'features_eye-dropper', '87f643e2-de02-41b2-bc4b-867273fe0295', '系统级取色器', 'System level color extractor', 'システムレベルの色取り機です', '系統級取色器', '2024-09-23 06:03:21.987', '2024-09-23 06:03:21.987');
+INSERT INTO "public"."Internalization" VALUES ('4ae027e5-2d9c-4418-b05f-d1a67c7de46a', 'features_vue-office', '87f643e2-de02-41b2-bc4b-867273fe0295', '文件预览', 'File preview', 'ファイルプレビューです', '文件預覽', '2024-09-23 07:38:37.576', '2024-09-23 07:38:37.576');
+INSERT INTO "public"."Internalization" VALUES ('fe89efbc-0701-479c-b730-bc7a39fc7d4c', 'features_flow', '87f643e2-de02-41b2-bc4b-867273fe0295', '流程图', 'Flow chart', 'フロー図です', '流程圖', '2024-09-25 01:33:59.786', '2024-09-25 01:33:59.786');
+INSERT INTO "public"."Internalization" VALUES ('de655676-d5c2-49c2-be98-22dda6f5d856', 'features_waterfall', '87f643e2-de02-41b2-bc4b-867273fe0295', '瀑布流', 'Waterfall', '滝が流れます', '瀑布流', '2024-09-26 03:37:38.76', '2024-09-26 03:37:38.76');
+INSERT INTO "public"."Internalization" VALUES ('c0beb0d6-76e5-47f9-b248-05f72c9869d8', 'features_swiper', '87f643e2-de02-41b2-bc4b-867273fe0295', 'Swiper', 'Swiper', 'Swiper', 'Swiper', '2024-09-26 12:08:49.361', '2024-09-26 12:08:49.361');
+INSERT INTO "public"."Internalization" VALUES ('82f576e0-b19c-4c68-ac06-db7eab6af7a9', 'swiper', '353a778e-3121-4593-bb58-2cbbd2136ad1', '', '', '', '', '2024-09-29 06:15:35.259', '2024-09-29 06:15:35.259');
+INSERT INTO "public"."Internalization" VALUES ('7da4bb75-a7b1-4006-b354-e6f2dea0475c', 'cube', '82f576e0-b19c-4c68-ac06-db7eab6af7a9', '方块', 'Cube', 'キューブです', '方塊', '2024-09-29 06:17:09.666', '2024-09-29 06:17:09.666');
+INSERT INTO "public"."Internalization" VALUES ('99bc9b27-22f8-477d-b63f-763f763da5fc', 'flip', '82f576e0-b19c-4c68-ac06-db7eab6af7a9', '翻转', 'Flip', '反転します', '翻轉', '2024-09-29 06:17:49.827', '2024-09-29 06:17:49.827');
+INSERT INTO "public"."Internalization" VALUES ('406f9d89-f966-41b5-b7fe-2d0d503d2193', 'card', '82f576e0-b19c-4c68-ac06-db7eab6af7a9', '卡片特效', 'Card effect', 'カードエフェクト', '卡片特效', '2024-09-29 06:19:14.791', '2024-09-29 06:19:14.791');
+INSERT INTO "public"."Internalization" VALUES ('42fd03de-2738-4b34-9550-7675994273f6', 'coverFlow', '82f576e0-b19c-4c68-ac06-db7eab6af7a9', '3d流翻转', '3d stream flip', '3dストリームのロールオーバです', '3d流翻轉', '2024-09-29 06:20:15.672', '2024-09-29 06:20:15.672');
+INSERT INTO "public"."Internalization" VALUES ('7282e303-e0ef-4694-8f95-6b7fe7e750dd', 'thumbnail', '82f576e0-b19c-4c68-ac06-db7eab6af7a9', '缩略图', 'Thumbnail', 'サムネイル画像です', '縮略圖', '2024-09-29 06:21:02.127', '2024-09-29 06:21:02.127');
+INSERT INTO "public"."Internalization" VALUES ('3de23180-3690-402b-a4de-058734d2a892', 'creative', '82f576e0-b19c-4c68-ac06-db7eab6af7a9', '创意效果', 'Creative', 'クリエイティブ効果です', '創意效果', '2024-09-29 06:21:39.469', '2024-09-29 06:21:39.469');
+INSERT INTO "public"."Internalization" VALUES ('a9600b1b-2ba8-4015-973e-af0720b1777e', 'visual', '82f576e0-b19c-4c68-ac06-db7eab6af7a9', '横向循环焦点图片展示', 'Horizontal loop focus picture display', '横回りのフォーカス画像です', '橫向循環焦點圖片展示', '2024-09-29 06:22:26.122', '2024-09-29 06:22:26.122');
+INSERT INTO "public"."Internalization" VALUES ('2d1fe946-9f1e-4e0f-8394-abc611ac7ca2', 'print', '353a778e-3121-4593-bb58-2cbbd2136ad1', '', '', '', '', '2024-09-29 06:24:58.367', '2024-09-29 06:24:58.367');
+INSERT INTO "public"."Internalization" VALUES ('39660da8-e990-4755-a462-404263ea769a', 'fullScreen', '2d1fe946-9f1e-4e0f-8394-abc611ac7ca2', '全屏打印', 'Full-screen printing', '全画面印刷です', '全屏打印', '2024-09-29 06:26:01.682', '2024-09-29 06:26:01.682');
+INSERT INTO "public"."Internalization" VALUES ('9df1de44-366b-41fa-9074-928ab0cf9fbe', 'instruction', '2d1fe946-9f1e-4e0f-8394-abc611ac7ca2', '指令打印', 'Instruction printing', '命令印刷です', '指令打印', '2024-09-29 06:26:40.001', '2024-09-29 06:26:40.001');
+INSERT INTO "public"."Internalization" VALUES ('3ed57a4c-51bf-4dcb-ae66-2a84c6795a0f', 'method', '2d1fe946-9f1e-4e0f-8394-abc611ac7ca2', '方法打印', 'Method printing', '方法印刷します', '方法打印', '2024-09-29 06:27:17.581', '2024-09-29 06:27:17.581');
+INSERT INTO "public"."Internalization" VALUES ('c7c1f461-8aa7-440f-afa1-f4039b177cdd', 'ingoreImg', '2d1fe946-9f1e-4e0f-8394-abc611ac7ca2', '打印忽略 img 标签', 'Print ignore img tag', 'imgラベルを無視して印刷します', '打印忽略 img 標簽', '2024-09-29 06:27:59.883', '2024-09-29 06:27:59.883');
+INSERT INTO "public"."Internalization" VALUES ('8242edd1-3087-4952-b270-c5b0e96191c1', 'lazyload', '353a778e-3121-4593-bb58-2cbbd2136ad1', '', '', '', '', '2024-09-29 06:29:25.358', '2024-09-29 06:29:25.358');
+INSERT INTO "public"."Internalization" VALUES ('3fb0870f-491f-4e8e-8799-fda4b6433613', 'subTitle', '8242edd1-3087-4952-b270-c5b0e96191c1', '图片懒加载核心就是判断当前图片是否到了可视区域,基于 IntersectionObserver API来实现了图片的懒加载', 'The core of image lazy loading is to determine whether the current image is in the visible area, and it implements image lazy loading based on IntersectionObserver API', 'ピクチャラックローディングコアは、現在の画像が可視領域に来ているかどうかを判定するもので、IntersectionObserver APIに基づいて画像のラックローディングを実現します', '圖片懶加載核心就是判斷當前圖片是否到了可視區域,基於 IntersectionObserver API來實現了圖片的懶加載', '2024-09-29 06:30:35.28', '2024-09-29 06:30:35.28');
+INSERT INTO "public"."Internalization" VALUES ('ba527ce4-6eb3-4bd4-9ac1-bb1ba84a2aa5', 'colorthief', '353a778e-3121-4593-bb58-2cbbd2136ad1', '', '', '', '', '2024-09-29 06:31:10.536', '2024-09-29 06:31:10.536');
+INSERT INTO "public"."Internalization" VALUES ('a6cb795e-d904-4f8b-b413-ab546341e6a7', 'subTitle', 'ba527ce4-6eb3-4bd4-9ac1-bb1ba84a2aa5', '核心是使用色彩聚合算法提取图片主色调生成渐变背景', 'The core is to use the color aggregation algorithm to extract the main color of the image to generate the gradient background', '核心は、カラーアグリゲーションアルゴリズムを使って、画像のメインカラーを抽出し、グラデーション背景を生成することです', '核心是使用色彩聚合算法提取圖片主色調生成漸變背景', '2024-09-29 06:32:07.977', '2024-09-29 06:32:07.977');
+INSERT INTO "public"."Internalization" VALUES ('2c89b527-fcfc-41cf-a5b3-7e1ff8c95c24', 'eye-dropper', '353a778e-3121-4593-bb58-2cbbd2136ad1', '', '', '', '', '2024-09-29 06:32:49.48', '2024-09-29 06:32:49.48');
+INSERT INTO "public"."Internalization" VALUES ('f7651538-f049-4804-b8cb-cc82d126d2d8', 'subTitle', '2c89b527-fcfc-41cf-a5b3-7e1ff8c95c24', '可将取色器移动到浏览器窗口中任意位置,即可获取到颜色值', 'You can move the color picker anywhere in the browser window to get the color value', 'カラーファインダーをブラウザのウィンドウ内のどこに移働させても、色の値を取得できます', '可將取色器移動到瀏覽器窗口中任意位置,即可獲取到顏色值', '2024-09-29 06:33:52.933', '2024-09-29 06:33:52.933');
+INSERT INTO "public"."Internalization" VALUES ('8c9a751d-d45f-4528-a7b2-9d1a58a4daa7', 'open', '2c89b527-fcfc-41cf-a5b3-7e1ff8c95c24', '打开取色器', 'Open the color extractor', '色取りをオンにします', '打開取色器', '2024-09-29 06:34:24.909', '2024-09-29 06:34:24.909');
+INSERT INTO "public"."Internalization" VALUES ('25bb875f-b122-4821-985b-8e26f4075d8e', 'cancel', '2c89b527-fcfc-41cf-a5b3-7e1ff8c95c24', '用户取消取色!', 'User cancels fetching color!', 'ユーザーは色取りをキャンセルします!', '用戶取消取色!', '2024-09-29 06:35:27.523', '2024-09-29 06:35:27.523');
+INSERT INTO "public"."Internalization" VALUES ('bee87aa7-9e4f-4ce0-b5b2-bcf9525263c3', 'support', '2c89b527-fcfc-41cf-a5b3-7e1ff8c95c24', '你的浏览器不支持EyeDropper', 'Your browser does not support EyeDropper', 'ブラウザはEyeDropperをサポートしていません', '你的瀏覽器不支持EyeDroppe', '2024-09-29 06:36:14.348', '2024-09-29 06:36:14.348');
+INSERT INTO "public"."Internalization" VALUES ('23852d38-9154-4cdb-905e-30e711cece7d', 'vue-office', '353a778e-3121-4593-bb58-2cbbd2136ad1', '', '', '', '', '2024-09-29 06:37:29.099', '2024-09-29 06:37:29.099');
+INSERT INTO "public"."Internalization" VALUES ('10d21a4d-2f64-4a1c-babc-249bfebb915f', 'docs', '23852d38-9154-4cdb-905e-30e711cece7d', 'Docs 文件预览', 'Docs file preview', 'Docsファイルプレビューです', 'Docs 文件預覽', '2024-09-29 06:38:11.638', '2024-09-29 06:38:11.638');
+INSERT INTO "public"."Internalization" VALUES ('709b1f87-fdcc-4224-a0ad-1fb99899d5bd', 'pdf', '23852d38-9154-4cdb-905e-30e711cece7d', 'Pdf 文件预览', 'Pdf file preview', 'Pdfファイルのプレビューです', 'Pdf 文件預覽', '2024-09-29 06:39:24.593', '2024-09-29 06:39:24.593');
+INSERT INTO "public"."Internalization" VALUES ('7520e584-b002-4064-88af-117caa587534', 'excel', '23852d38-9154-4cdb-905e-30e711cece7d', 'Excel 文件预览', 'Excel File Preview', 'Excelファイルのプレビューです', 'Excel 文件預覽', '2024-09-29 06:38:47.617', '2024-09-29 06:38:47.617');
+INSERT INTO "public"."Internalization" VALUES ('1b290b83-de64-4165-a848-fc8edbb12a22', 'upload', '23852d38-9154-4cdb-905e-30e711cece7d', '上传本地文件', 'Upload local files', 'ローカルファイルをアップロードします', '上傳本地文件', '2024-09-29 06:40:51.277', '2024-09-29 06:40:51.277');
+INSERT INTO "public"."Internalization" VALUES ('f83a10c5-b47e-4067-a6aa-6b819cca9a83', 'waterfall', '353a778e-3121-4593-bb58-2cbbd2136ad1', '', '', '', '', '2024-09-29 06:41:54.11', '2024-09-29 06:41:54.11');
+INSERT INTO "public"."Internalization" VALUES ('5d6fdab9-0fcc-426c-8206-28eb4d4424a6', 'more', 'f83a10c5-b47e-4067-a6aa-6b819cca9a83', '加载更多', 'Load more', 'もっとロードします', '加載更多', '2024-09-29 06:42:51.509', '2024-09-29 06:42:51.509');
+INSERT INTO "public"."Internalization" VALUES ('38673bbe-12a8-4a19-ad33-34cdddcf8a8b', 'noMore', 'f83a10c5-b47e-4067-a6aa-6b819cca9a83', '客官,已经到底了', 'Guest officer, it''s all over', 'お客さん,もう終わりました', '客官,已經到底了', '2024-09-29 06:43:35.95', '2024-09-29 06:43:35.95');
+INSERT INTO "public"."Internalization" VALUES ('3e2803fa-79b3-4047-ba47-2445bee79d0f', 'vue-directive', '353a778e-3121-4593-bb58-2cbbd2136ad1', '', '', '', '', '2024-09-29 06:45:17.044', '2024-09-29 06:45:17.044');
+INSERT INTO "public"."Internalization" VALUES ('165ee990-4a92-4e8c-8844-4e3e2a1904a7', 'v-copy', '3e2803fa-79b3-4047-ba47-2445bee79d0f', '', '', '', '', '2024-09-29 06:45:49.015', '2024-09-29 06:45:49.015');
+INSERT INTO "public"."Internalization" VALUES ('defa8a07-65ba-4ec6-852f-b54de1b2cb0d', 'title', '165ee990-4a92-4e8c-8844-4e3e2a1904a7', '复制指令 v-copy', 'Copy instruction v-copy', 'コピー命令v-copyです', '復製指令 v-copy', '2024-09-29 06:46:39.734', '2024-09-29 06:46:39.734');
+INSERT INTO "public"."Internalization" VALUES ('8045a56e-7924-4846-97a3-faf6c83e5b27', 'button', '165ee990-4a92-4e8c-8844-4e3e2a1904a7', '复制', 'Copy', '複製します', '復製', '2024-09-29 06:47:13.237', '2024-09-29 06:47:13.237');
+INSERT INTO "public"."Internalization" VALUES ('7cd8950b-3c08-4252-96e4-1e20359be81e', 'v-longpress', '3e2803fa-79b3-4047-ba47-2445bee79d0f', '', '', '', '', '2024-09-29 06:47:31.303', '2024-09-29 06:47:31.303');
+INSERT INTO "public"."Internalization" VALUES ('9be4a10f-59e9-4294-9c8b-2b8c28ad178a', 'title', '7cd8950b-3c08-4252-96e4-1e20359be81e', '长按指令 v-longpress', 'Long press the command v-longpress', 'コマンドを長押ししますv-longpress', '長按指令 v-longpress', '2024-09-29 06:48:14.279', '2024-09-29 06:48:14.279');
+INSERT INTO "public"."Internalization" VALUES ('c7dd98f7-b6ee-4b9d-9edc-19bb7ba90bcc', 'button', '7cd8950b-3c08-4252-96e4-1e20359be81e', '长按1秒钟触发', 'Press and hold for 1 second to trigger', 'トリガーを1秒長押しするだけです', '長按1秒鐘觸發', '2024-09-29 06:48:56.436', '2024-09-29 06:48:56.436');
+INSERT INTO "public"."Internalization" VALUES ('e211e2c0-115e-4447-8195-0f457a03dd95', 'v-debounce', '3e2803fa-79b3-4047-ba47-2445bee79d0f', '', '', '', '', '2024-09-29 06:49:04.703', '2024-09-29 06:49:04.703');
+INSERT INTO "public"."Internalization" VALUES ('34c202db-1c4a-4d25-9363-d2a3ad9314ea', 'title', 'e211e2c0-115e-4447-8195-0f457a03dd95', '防抖指令 v-debounce', 'Anti-shake command v-debounce', '手ブレ補正コマンドv-debounceです', '防抖指令 v-debounce', '2024-09-29 06:49:53.021', '2024-09-29 06:49:53.021');
+INSERT INTO "public"."Internalization" VALUES ('01ce614d-3beb-4667-998f-c5c00329d7a0', 'button', 'e211e2c0-115e-4447-8195-0f457a03dd95', '最后一次点击1秒钟后触发', 'Triggered 1 second after the last click', '最後のクリックから1秒後に起動します', '最後一次點擊1秒鐘後觸發', '2024-09-29 06:50:34.578', '2024-09-29 06:50:34.578');
+INSERT INTO "public"."Internalization" VALUES ('f081ab25-d1f7-4727-b84d-71a3de92e078', 'v-throllte', '3e2803fa-79b3-4047-ba47-2445bee79d0f', '', '', '', '', '2024-09-29 06:50:43.643', '2024-09-29 06:50:43.643');
+INSERT INTO "public"."Internalization" VALUES ('d49dd907-4fb5-4b77-bab0-03091dfde1f1', 'title', 'f081ab25-d1f7-4727-b84d-71a3de92e078', '节流指令 v-throllte', 'Throttle instruction v-throllte', 'スロットル命令v−throllteです', '節流指令 v-throllte', '2024-09-29 06:51:26.503', '2024-09-29 06:51:26.503');
+INSERT INTO "public"."Internalization" VALUES ('1589687c-4e64-4d5e-aa4a-e2b042450e41', 'button', 'f081ab25-d1f7-4727-b84d-71a3de92e078', '1秒钟内只触发一次', 'It only triggers once a second', '1秒間に1回だけトリガーがかかります', '1秒鐘內只觸發一次', '2024-09-29 06:52:01.878', '2024-09-29 06:52:01.878');
+INSERT INTO "public"."Internalization" VALUES ('2b850e0c-afd0-44e2-8e3c-2a0b879fde43', 'v-emoji', '3e2803fa-79b3-4047-ba47-2445bee79d0f', '', '', '', '', '2024-09-29 06:52:11.778', '2024-09-29 06:52:11.778');
+INSERT INTO "public"."Internalization" VALUES ('82ec4a60-ee32-4022-bed6-3167f40d7294', 'title', '2b850e0c-afd0-44e2-8e3c-2a0b879fde43', '禁止表情和特殊字符 v-emoji', 'Emojis and special character V-emojis are prohibited', '絵文字や特殊文字「v-emoji」は禁止です', '禁止表情和特殊字符 v-emoji', '2024-09-29 06:52:39.804', '2024-09-29 06:52:39.804');
+INSERT INTO "public"."Internalization" VALUES ('836f7d2c-5fe8-4448-bbad-c20eeb3d52bf', 'placeholder', '2b850e0c-afd0-44e2-8e3c-2a0b879fde43', '禁止输入@#%^等字符', 'Characters such as @#%^ are prohibited', '@#%^などの入力は禁止です', '禁止輸入@#%^等字符', '2024-09-29 06:53:38.73', '2024-09-29 06:53:38.73');
+INSERT INTO "public"."Internalization" VALUES ('2a638da4-9a8e-4f3b-9a3d-1ae6b1678e24', 'v-input', '3e2803fa-79b3-4047-ba47-2445bee79d0f', '', '', '', '', '2024-09-29 06:53:49.621', '2024-09-29 06:53:49.621');
+INSERT INTO "public"."Internalization" VALUES ('b255f3db-124f-4f45-a52e-5bdc7e14e6bb', 'title', '2a638da4-9a8e-4f3b-9a3d-1ae6b1678e24', '输入框规则指令 v-input', 'Input box rule instruction v-input', '入力ボックスルール命令v-inputです', '輸入框規則指令 v-input', '2024-09-29 06:54:30.003', '2024-09-29 06:54:30.003');
+INSERT INTO "public"."Internalization" VALUES ('c4c9d362-b59d-40b5-98d9-2d50d09ae57e', 'placeholder', '2a638da4-9a8e-4f3b-9a3d-1ae6b1678e24', '数字+两位小数', 'Number + two decimal places', '数字+小数2桁です', '數字+兩位小數', '2024-09-29 06:55:04.032', '2024-09-29 06:55:04.032');
+INSERT INTO "public"."Internalization" VALUES ('6ae4a009-5979-4e2d-bca9-6efec022dba2', 'v-ripple', '3e2803fa-79b3-4047-ba47-2445bee79d0f', '', '', '', '', '2024-09-29 06:55:15.147', '2024-09-29 06:55:15.147');
+INSERT INTO "public"."Internalization" VALUES ('dc72d98d-3840-454c-b559-70f0489f885a', 'title', '6ae4a009-5979-4e2d-bca9-6efec022dba2', '水波纹指令 v-ripple', 'Water ripple instruction v-ripple', '水波紋指令v-rippleです', '水波紋指令 v-ripple', '2024-09-29 06:55:56.831', '2024-09-29 06:55:56.831');
+INSERT INTO "public"."Internalization" VALUES ('70134c26-0f9a-4e45-abe1-9fbd4a5a76c7', 'button', '6ae4a009-5979-4e2d-bca9-6efec022dba2', '水波纹指令', 'Water ripple command', '水波紋指令です', '水波紋指令', '2024-09-29 06:56:32.961', '2024-09-29 06:56:32.961');
+INSERT INTO "public"."Internalization" VALUES ('b2ca2e2c-fbd6-4928-97d8-6f63b7142f4b', 'v-lazyLoad', '3e2803fa-79b3-4047-ba47-2445bee79d0f', '', '', '', '', '2024-09-29 06:56:38.51', '2024-09-29 06:56:38.51');
+INSERT INTO "public"."Internalization" VALUES ('e6789b07-1761-4170-9f13-3248d6990037', 'title', 'b2ca2e2c-fbd6-4928-97d8-6f63b7142f4b', '懒加载指令 v-lazyLoad', 'Lazy load instruction v-lazyLoad', 'v-lazyload命令です', '懶加載指令 v-lazyLoad', '2024-09-29 06:57:28.113', '2024-09-29 06:57:28.113');
+INSERT INTO "public"."Internalization" VALUES ('cfcc5d1e-88c7-4ce4-974d-7557465905d2', 'button', 'b2ca2e2c-fbd6-4928-97d8-6f63b7142f4b', '懒加载指令', 'Lazy load instruction', '怠惰ロード命令です', '懶加載指令', '2024-09-29 06:58:04.6', '2024-09-29 06:58:04.6');
+INSERT INTO "public"."Internalization" VALUES ('b17bce54-c43d-4a3e-8156-749f7fdb3740', 'success', '3e2803fa-79b3-4047-ba47-2445bee79d0f', '你太棒啦!', 'You''re awesome!', 'あなたは素晴らしいです!', '你太棒啦!', '2024-09-29 06:59:00.618', '2024-09-29 06:59:00.618');
+INSERT INTO "public"."Internalization" VALUES ('646e3ce8-89f2-4a52-9b47-c187d9523229', 'city', '3f05721e-70cd-4f93-bc94-f6f2951d935f', '所在城市', 'Home city', '所在する都市です', '所在城市', '2024-10-31 02:13:37.339', '2024-10-31 02:13:37.339');
+
+-- ----------------------------
+-- Primary Key structure for table Internalization
+-- ----------------------------
+ALTER TABLE "public"."Internalization" ADD CONSTRAINT "Internalization_pkey" PRIMARY KEY ("id");
+
+-- ----------------------------
+-- Foreign Keys structure for table Internalization
+-- ----------------------------
+ALTER TABLE "public"."Internalization" ADD CONSTRAINT "Internalization_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "public"."Internalization" ("id") ON DELETE SET NULL ON UPDATE CASCADE;

+ 54 - 0
postgreSQL/Log.sql

@@ -0,0 +1,54 @@
+/*
+ Navicat Premium Dump SQL
+
+ Source Server         : postgreSQL
+ Source Server Type    : PostgreSQL
+ Source Server Version : 160003 (160003)
+ Source Host           : localhost:5432
+ Source Catalog        : vue3-admin
+ Source Schema         : public
+
+ Target Server Type    : PostgreSQL
+ Target Server Version : 160003 (160003)
+ File Encoding         : 65001
+
+ Date: 31/10/2024 10:16:54
+*/
+
+
+-- ----------------------------
+-- Table structure for Log
+-- ----------------------------
+DROP TABLE IF EXISTS "public"."Log";
+CREATE TABLE "public"."Log" (
+  "id" text COLLATE "pg_catalog"."default" NOT NULL,
+  "userId" text COLLATE "pg_catalog"."default" NOT NULL,
+  "ip" text COLLATE "pg_catalog"."default" NOT NULL,
+  "action" text COLLATE "pg_catalog"."default" NOT NULL,
+  "method" "public"."Method" NOT NULL,
+  "params" jsonb NOT NULL,
+  "os" text COLLATE "pg_catalog"."default" NOT NULL,
+  "browser" text COLLATE "pg_catalog"."default" NOT NULL,
+  "province" text COLLATE "pg_catalog"."default",
+  "city" text COLLATE "pg_catalog"."default",
+  "adcode" text COLLATE "pg_catalog"."default",
+  "createdAt" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP
+)
+;
+
+-- ----------------------------
+-- Records of Log
+-- ----------------------------
+INSERT INTO "public"."Log" VALUES ('6725fc4f-bfb1-4323-8a16-133ed81d127f', 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f', '::1', '/auth/login', 'POST', '{"password": "abc123456", "userName": "Admin", "captchaCode": "9"}', 'Windows 10', 'Chrome', NULL, NULL, NULL, '2024-10-31 02:12:24.756');
+INSERT INTO "public"."Log" VALUES ('fd6d4070-a1a8-4fd9-bd37-e0d5ddd5f55f', 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f', '::1', '/auth/juejin', 'POST', '{"cursor": "0", "user_id": "1917147257534279", "sort_type": 2}', 'Windows 10', 'Chrome', NULL, NULL, NULL, '2024-10-31 02:12:26.049');
+INSERT INTO "public"."Log" VALUES ('c957011b-4984-4448-8a71-9ba2f440a512', 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f', '::1', '/system/internalization', 'POST', '{"enUS": "Home city", "jaJP": "所在する都市です", "name": "city", "zhCN": "所在城市", "zhTW": "所在城市", "parentId": "3f05721e-70cd-4f93-bc94-f6f2951d935f"}', 'Windows 10', 'Chrome', NULL, NULL, NULL, '2024-10-31 02:13:37.335');
+
+-- ----------------------------
+-- Primary Key structure for table Log
+-- ----------------------------
+ALTER TABLE "public"."Log" ADD CONSTRAINT "Log_pkey" PRIMARY KEY ("id");
+
+-- ----------------------------
+-- Foreign Keys structure for table Log
+-- ----------------------------
+ALTER TABLE "public"."Log" ADD CONSTRAINT "Log_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE;

+ 136 - 0
postgreSQL/Menu.sql

@@ -0,0 +1,136 @@
+/*
+ Navicat Premium Dump SQL
+
+ Source Server         : postgreSQL
+ Source Server Type    : PostgreSQL
+ Source Server Version : 160003 (160003)
+ Source Host           : localhost:5432
+ Source Catalog        : vue3-admin
+ Source Schema         : public
+
+ Target Server Type    : PostgreSQL
+ Target Server Version : 160003 (160003)
+ File Encoding         : 65001
+
+ Date: 31/10/2024 10:17:01
+*/
+
+
+-- ----------------------------
+-- Table structure for Menu
+-- ----------------------------
+DROP TABLE IF EXISTS "public"."Menu";
+CREATE TABLE "public"."Menu" (
+  "id" text COLLATE "pg_catalog"."default" NOT NULL,
+  "title" text COLLATE "pg_catalog"."default" NOT NULL,
+  "type" "public"."MenuType" NOT NULL DEFAULT 'MENU'::"MenuType",
+  "parentId" text COLLATE "pg_catalog"."default",
+  "name" text COLLATE "pg_catalog"."default",
+  "path" text COLLATE "pg_catalog"."default",
+  "component" text COLLATE "pg_catalog"."default",
+  "meta" jsonb,
+  "sort" int4 NOT NULL,
+  "permission" text COLLATE "pg_catalog"."default",
+  "createdAt" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  "updatedAt" timestamp(3) NOT NULL,
+  "props" jsonb
+)
+;
+
+-- ----------------------------
+-- Records of Menu
+-- ----------------------------
+INSERT INTO "public"."Menu" VALUES ('dea4e038-592f-4532-ac86-c7de25a3416c', '组织管理', 'MENU', '03404a66-50aa-4b21-8c93-9dcddaeffdb7', 'administrative_organization', '/administrative/organization', 'view.administrative_organization', '{"icon": "ri:exchange-2-line", "order": 0, "title": "administrative_organization", "i18nKey": "route.administrative_organization", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 1, NULL, '2024-08-20 06:18:01.518', '2024-08-20 06:18:08.978', NULL);
+INSERT INTO "public"."Menu" VALUES ('8be52db9-1856-4f14-8b2f-12c51ba45a3e', '新增', 'BUTTON', 'dea4e038-592f-4532-ac86-c7de25a3416c', NULL, NULL, NULL, NULL, 1, 'administrative:organization:add', '2024-08-22 08:13:01.987', '2024-08-22 08:13:01.987', NULL);
+INSERT INTO "public"."Menu" VALUES ('4fc642f4-18bb-4b18-980b-7e41e804720c', '个人中心', 'MENU', NULL, 'user-center', '/user-center', 'layout.base$view.user-center', '{"icon": "ri:id-card-line", "order": 3, "title": "user-center", "i18nKey": "route.user-center", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 3, NULL, '2024-08-20 09:53:42.835', '2024-09-04 02:17:05.549', NULL);
+INSERT INTO "public"."Menu" VALUES ('4d238c00-d8c0-4ed2-a803-41caf772820e', '关于', 'MENU', NULL, 'about', '/about', 'layout.base$view.about', '{"icon": "fluent:book-information-24-regular", "order": 6, "title": "about", "i18nKey": "route.about", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 5, NULL, '2024-08-20 06:31:49.783', '2024-09-10 02:16:34.961', '{}');
+INSERT INTO "public"."Menu" VALUES ('8f16a2cd-b613-4419-bfa5-996f16beaa6a', '首页', 'MENU', NULL, 'home', '/home', 'layout.base$view.home', '{"icon": "mdi:monitor-dashboard", "order": 1, "title": "home", "i18nKey": "route.home", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 1, NULL, '2024-08-19 09:05:42.591', '2024-08-20 06:30:37.079', NULL);
+INSERT INTO "public"."Menu" VALUES ('1ee566d9-d5ef-456a-8009-d67bb026b4b0', '用户管理', 'MENU', '572c5097-d28f-48b4-899d-3aaf46b8d668', 'system-manage_user-manage', '/system-manage/user-manage', 'view.system-manage_user-manage', '{"icon": "ri:user-settings-line", "order": 0, "title": "system-manage_user-manage", "i18nKey": "route.system-manage_user-manage", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 1, NULL, '2024-08-20 06:24:54.605', '2024-09-04 02:17:37.394', NULL);
+INSERT INTO "public"."Menu" VALUES ('03404a66-50aa-4b21-8c93-9dcddaeffdb7', '智能行政', 'DIRECTORY', NULL, 'administrative', '/administrative', 'layout.base', '{"icon": "ri:quill-pen-line", "order": 2, "title": "administrative", "i18nKey": "route.administrative", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 2, NULL, '2024-08-20 06:11:55.369', '2024-08-20 06:20:20.263', NULL);
+INSERT INTO "public"."Menu" VALUES ('d4d48216-c56d-4620-98b3-4ff8ce8fbc3b', '登录页', 'DIRECTORY', NULL, 'login', '/login', 'layout.blank$view.login', '{"order": 0, "title": "login", "i18nKey": "route.login", "constant": true, "multiTab": false, "keepAlive": false, "hideInMenu": true}', 6, NULL, '2024-08-20 07:06:39.93', '2024-09-10 02:17:16.492', '{}');
+INSERT INTO "public"."Menu" VALUES ('3f27c671-cfe4-48d2-a240-9f152c9a0c3a', '500', 'MENU', NULL, '500', '/500', 'layout.blank$view.500', '{"order": 0, "title": "500", "i18nKey": "route.500", "constant": true, "multiTab": false, "keepAlive": false, "hideInMenu": true}', 9, NULL, '2024-08-20 06:38:08.365', '2024-09-10 02:18:09.676', '{}');
+INSERT INTO "public"."Menu" VALUES ('c4bb98dd-e417-438b-8fe5-7b27e2921e72', '编辑', 'BUTTON', 'dea4e038-592f-4532-ac86-c7de25a3416c', NULL, NULL, NULL, NULL, 1, 'administrative:organization:edit', '2024-08-22 08:13:36.151', '2024-08-22 08:13:36.151', NULL);
+INSERT INTO "public"."Menu" VALUES ('76402592-28e6-4575-9454-b38133652fa8', '删除', 'BUTTON', 'dea4e038-592f-4532-ac86-c7de25a3416c', NULL, NULL, NULL, NULL, 1, 'administrative:organization:delete', '2024-08-22 08:13:56.316', '2024-08-22 08:13:56.316', NULL);
+INSERT INTO "public"."Menu" VALUES ('0916a1b8-bf6f-4732-9c3c-c0b834c9e1cc', '新增', 'BUTTON', '5dc9be35-dfad-493e-99c4-fdca4ddff1f5', NULL, NULL, NULL, NULL, 1, 'administrative:post-manage:add', '2024-08-22 08:17:31.509', '2024-08-22 08:17:31.509', NULL);
+INSERT INTO "public"."Menu" VALUES ('db9d9316-ad43-41f2-9060-f6f55a6d0fd2', '编辑', 'BUTTON', '5dc9be35-dfad-493e-99c4-fdca4ddff1f5', NULL, NULL, NULL, NULL, 1, 'administrative:post-manage:edit', '2024-08-22 08:17:59.364', '2024-08-22 08:17:59.364', NULL);
+INSERT INTO "public"."Menu" VALUES ('4918cc69-4050-4929-9113-e5cb7e67b848', '删除', 'BUTTON', '5dc9be35-dfad-493e-99c4-fdca4ddff1f5', NULL, NULL, NULL, NULL, 1, 'administrative:post-manage:delete', '2024-08-22 08:18:28.673', '2024-08-22 08:18:28.673', NULL);
+INSERT INTO "public"."Menu" VALUES ('ea793941-1ca1-4e23-ac0e-784d3a95743a', '新增', 'BUTTON', '1ee566d9-d5ef-456a-8009-d67bb026b4b0', NULL, NULL, NULL, NULL, 1, 'system-manage:user-manage:add', '2024-08-22 08:19:02.046', '2024-08-22 08:19:02.046', NULL);
+INSERT INTO "public"."Menu" VALUES ('acfd4d4c-4b12-46b9-9a11-e85c2fc8e667', '编辑', 'BUTTON', '1ee566d9-d5ef-456a-8009-d67bb026b4b0', NULL, NULL, NULL, NULL, 1, 'system-manage:user-manage:edit', '2024-08-22 08:19:27.088', '2024-08-22 08:19:27.088', NULL);
+INSERT INTO "public"."Menu" VALUES ('a66a0e69-cd75-4460-b766-1ad52a82ac10', '删除', 'BUTTON', '1ee566d9-d5ef-456a-8009-d67bb026b4b0', NULL, NULL, NULL, NULL, 1, 'system-manage:user-manage:delete', '2024-08-22 08:19:46.595', '2024-08-22 08:19:46.595', NULL);
+INSERT INTO "public"."Menu" VALUES ('61da313d-4b5f-40b4-9bc3-55b57ebf18d1', '新增', 'BUTTON', '28a745e9-ff3a-49c2-bebc-e269146652e6', NULL, NULL, NULL, NULL, 1, 'system-manage:menu-manage:add', '2024-08-22 08:20:26.409', '2024-08-22 08:20:26.409', NULL);
+INSERT INTO "public"."Menu" VALUES ('572c5097-d28f-48b4-899d-3aaf46b8d668', '系统管理', 'DIRECTORY', NULL, 'system-manage', '/system-manage', 'layout.base', '{"icon": "ri:settings-2-line", "order": 5, "title": "system-manage", "i18nKey": "route.system-manage", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 4, NULL, '2024-08-20 06:24:04.955', '2024-09-10 02:16:16.165', '{}');
+INSERT INTO "public"."Menu" VALUES ('5dc9be35-dfad-493e-99c4-fdca4ddff1f5', '岗位管理', 'MENU', '03404a66-50aa-4b21-8c93-9dcddaeffdb7', 'administrative_post-manage', '/administrative/post-manage', 'view.administrative_post-manage', '{"icon": "ri:contacts-book-3-line", "order": 0, "title": "administrative_post-manage", "i18nKey": "route.administrative_post-manage", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 2, NULL, '2024-08-20 06:19:52.117', '2024-09-04 02:16:54.951', NULL);
+INSERT INTO "public"."Menu" VALUES ('28a745e9-ff3a-49c2-bebc-e269146652e6', '菜单管理', 'MENU', '572c5097-d28f-48b4-899d-3aaf46b8d668', 'system-manage_menu-manage', '/system-manage/menu-manage', 'view.system-manage_menu-manage', '{"icon": "ri:route-fill", "order": 0, "title": "system-manage_menu-manage", "i18nKey": "route.system-manage_menu-manage", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 2, NULL, '2024-08-20 06:26:36.083', '2024-09-04 02:17:49.85', NULL);
+INSERT INTO "public"."Menu" VALUES ('aaf9caab-e4cc-491c-bf9c-d5fe81b9d867', '国际化', 'MENU', '572c5097-d28f-48b4-899d-3aaf46b8d668', 'system-manage_internalization', '/system-manage/internalization', 'view.system-manage_internalization', '{"icon": "ri:global-line", "order": 0, "title": "system-manage_internalization", "i18nKey": "route.system-manage_internalization", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 3, NULL, '2024-08-20 06:29:01.881', '2024-09-04 02:18:14.03', NULL);
+INSERT INTO "public"."Menu" VALUES ('5f504e9d-7e9e-4474-9747-cce41b41599f', '403', 'MENU', NULL, '403', '/403', 'layout.blank$view.403', '{"order": 0, "title": "403", "i18nKey": "route.403", "constant": true, "multiTab": false, "keepAlive": false, "hideInMenu": true}', 7, NULL, '2024-08-20 06:36:06.285', '2024-09-10 02:17:34.406', '{}');
+INSERT INTO "public"."Menu" VALUES ('7db840cf-4d26-497f-9821-227dca0787d9', '404', 'MENU', NULL, '404', '/404', 'layout.blank$view.404', '{"order": 0, "title": "404", "i18nKey": "route.404", "constant": true, "multiTab": false, "keepAlive": false, "hideInMenu": true}', 8, NULL, '2024-08-20 06:37:27.573', '2024-09-10 02:17:55.262', '{}');
+INSERT INTO "public"."Menu" VALUES ('75323ec9-1a06-4159-b850-6360fb868f29', 'iframe-page', 'MENU', NULL, 'iframe-page', '/iframe-page/:url', 'layout.base$view.iframe-page', '{"order": 0, "title": "iframe-page", "i18nKey": "route.iframe-page", "constant": true, "multiTab": false, "keepAlive": true, "hideInMenu": true}', 10, NULL, '2024-08-20 07:05:43.315', '2024-09-10 02:18:22.708', '{}');
+INSERT INTO "public"."Menu" VALUES ('e3f98b23-30a9-4b6b-b15c-fe08b13baf5f', '新增', 'BUTTON', 'aaf9caab-e4cc-491c-bf9c-d5fe81b9d867', NULL, NULL, NULL, NULL, 1, 'system-manage:internalization:add', '2024-08-22 08:21:52.645', '2024-08-22 08:21:52.645', NULL);
+INSERT INTO "public"."Menu" VALUES ('f309088f-e63d-48a1-8dce-1b9409dfe0b0', '批量删除', 'BUTTON', '596eba6b-6b80-495a-bf9d-f90fdfb9e49d', NULL, NULL, NULL, NULL, 1, 'system-manage:operation-log:batch-delete', '2024-08-22 08:23:58.717', '2024-08-22 08:23:58.717', NULL);
+INSERT INTO "public"."Menu" VALUES ('7abbee43-cd32-4633-9702-2511eda28357', '新增', 'BUTTON', '2e7aa93e-978c-42e3-aef3-49ec2c7fa183', NULL, NULL, NULL, NULL, 1, 'system-manage:role-manage:add', '2024-08-22 08:31:12.317', '2024-08-22 08:31:12.317', NULL);
+INSERT INTO "public"."Menu" VALUES ('37191c9a-19b7-43aa-9ad5-369100f1407c', '编辑', 'BUTTON', '28a745e9-ff3a-49c2-bebc-e269146652e6', NULL, NULL, NULL, NULL, 1, 'system-manage:menu-manage:edit', '2024-08-22 08:20:52.452', '2024-08-22 08:20:52.452', NULL);
+INSERT INTO "public"."Menu" VALUES ('596eba6b-6b80-495a-bf9d-f90fdfb9e49d', '操作日志', 'MENU', '572c5097-d28f-48b4-899d-3aaf46b8d668', 'system-manage_operation-log', '/system-manage/operation-log', 'view.system-manage_operation-log', '{"icon": "ri:draft-line", "order": 0, "title": "system-manage_operation-log", "i18nKey": "route.system-manage_operation-log", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 4, NULL, '2024-08-20 06:30:11.766', '2024-09-04 02:18:26.169', NULL);
+INSERT INTO "public"."Menu" VALUES ('4bcb5d6b-f876-4e95-8e13-e847bcb18d5d', '编辑', 'BUTTON', 'aaf9caab-e4cc-491c-bf9c-d5fe81b9d867', NULL, NULL, NULL, NULL, 1, 'system-manage:internalization:edit', '2024-08-22 08:22:10.661', '2024-08-22 08:22:10.661', NULL);
+INSERT INTO "public"."Menu" VALUES ('7131adbe-2b2b-4233-ab50-e9ee1859b09b', '删除', 'BUTTON', 'aaf9caab-e4cc-491c-bf9c-d5fe81b9d867', NULL, NULL, NULL, NULL, 1, 'system-manage:internalization:delete', '2024-08-22 08:22:23.636', '2024-08-22 08:22:23.636', NULL);
+INSERT INTO "public"."Menu" VALUES ('848a03e4-25db-41f8-97bf-c154fa160c64', '删除', 'BUTTON', '596eba6b-6b80-495a-bf9d-f90fdfb9e49d', NULL, NULL, NULL, NULL, 1, 'system-manage:operation-log:delete', '2024-08-22 08:23:32.366', '2024-08-22 08:23:32.366', NULL);
+INSERT INTO "public"."Menu" VALUES ('a8304bfd-0b75-4203-aa30-24c0ee98d4f5', '编辑', 'BUTTON', '2e7aa93e-978c-42e3-aef3-49ec2c7fa183', NULL, NULL, NULL, NULL, 1, 'system-manage:role-manage:edit', '2024-08-22 08:31:27.964', '2024-08-22 08:31:27.964', NULL);
+INSERT INTO "public"."Menu" VALUES ('3064dd2b-38d6-46ba-965e-21a101da688c', '删除', 'BUTTON', '2e7aa93e-978c-42e3-aef3-49ec2c7fa183', NULL, NULL, NULL, NULL, 1, 'system-manage:role-manage:delete', '2024-08-22 08:31:43.239', '2024-08-22 08:31:43.239', NULL);
+INSERT INTO "public"."Menu" VALUES ('9e378453-357b-4395-a342-d53f98d6db46', '删除', 'BUTTON', '28a745e9-ff3a-49c2-bebc-e269146652e6', NULL, NULL, NULL, NULL, 1, 'system-manage:menu-manage:delete', '2024-08-22 08:21:07.695', '2024-08-22 08:21:07.695', NULL);
+INSERT INTO "public"."Menu" VALUES ('fd9ac9a5-be38-426c-b38a-8bda75420ffc', '查看', 'BUTTON', 'dea4e038-592f-4532-ac86-c7de25a3416c', NULL, NULL, NULL, NULL, 1, 'administrative:organization:view', '2024-08-23 05:37:09.583', '2024-08-23 05:37:09.583', NULL);
+INSERT INTO "public"."Menu" VALUES ('48d6f0b5-5b11-422c-bee9-d1caa8447966', '查看', 'BUTTON', '5dc9be35-dfad-493e-99c4-fdca4ddff1f5', NULL, NULL, NULL, NULL, 1, 'administrative:post-manage:view', '2024-08-23 05:50:11.134', '2024-08-23 05:50:11.134', NULL);
+INSERT INTO "public"."Menu" VALUES ('e1b37b30-e000-4c24-8976-8c9fa78042b0', '查看', 'BUTTON', '1ee566d9-d5ef-456a-8009-d67bb026b4b0', NULL, NULL, NULL, NULL, 1, 'system-manage:user-manage:view', '2024-08-23 05:51:07.705', '2024-08-23 05:51:07.705', NULL);
+INSERT INTO "public"."Menu" VALUES ('0c437ad9-c18e-46df-b2c1-c1330601ac3c', '查看', 'BUTTON', '28a745e9-ff3a-49c2-bebc-e269146652e6', NULL, NULL, NULL, NULL, 1, 'system-manage:menu-manage:view', '2024-08-23 05:52:04.806', '2024-08-23 05:52:04.806', NULL);
+INSERT INTO "public"."Menu" VALUES ('9ff718db-c9f9-4fd4-8cc2-d6212b74c336', '查看', 'BUTTON', '2e7aa93e-978c-42e3-aef3-49ec2c7fa183', NULL, NULL, NULL, NULL, 1, 'system-manage:role-manage:view', '2024-08-23 05:52:38.264', '2024-08-23 05:52:38.264', NULL);
+INSERT INTO "public"."Menu" VALUES ('6b52bc0a-f2b6-4422-8ef8-dde0c5b81f96', '查看', 'BUTTON', 'aaf9caab-e4cc-491c-bf9c-d5fe81b9d867', NULL, NULL, NULL, NULL, 1, 'system-manage:internalization:view', '2024-08-23 05:53:11.889', '2024-08-23 05:53:11.889', NULL);
+INSERT INTO "public"."Menu" VALUES ('52ff7472-67da-4f9b-ba90-ec5468492f32', '查看', 'BUTTON', '596eba6b-6b80-495a-bf9d-f90fdfb9e49d', NULL, NULL, NULL, NULL, 1, 'system-manage:operation-log:view', '2024-08-23 05:53:46.945', '2024-08-23 05:53:46.945', NULL);
+INSERT INTO "public"."Menu" VALUES ('e02f4271-4f9b-47e5-a76f-040db8404bd2', '新增', 'BUTTON', '74ca9688-7700-4322-b36f-e1180c5b996b', NULL, NULL, NULL, NULL, 1, 'administrative:message:add', '2024-09-02 09:03:35.181', '2024-09-02 09:03:35.181', NULL);
+INSERT INTO "public"."Menu" VALUES ('ad167628-1055-470c-90ba-f401c4edc621', '编辑', 'BUTTON', '74ca9688-7700-4322-b36f-e1180c5b996b', NULL, NULL, NULL, NULL, 1, 'administrative:message:edit', '2024-09-02 09:03:52.305', '2024-09-02 09:03:52.305', NULL);
+INSERT INTO "public"."Menu" VALUES ('db837491-6a97-412d-8668-32de8e286390', '删除', 'BUTTON', '74ca9688-7700-4322-b36f-e1180c5b996b', NULL, NULL, NULL, NULL, 1, 'administrative:message:delete', '2024-09-02 09:04:05.842', '2024-09-02 09:04:05.842', NULL);
+INSERT INTO "public"."Menu" VALUES ('45d1f4ea-a1e5-4e48-b6a7-141e1fa63b67', '查看', 'BUTTON', '74ca9688-7700-4322-b36f-e1180c5b996b', NULL, NULL, NULL, NULL, 1, 'administrative:message:view', '2024-09-02 09:04:20.88', '2024-09-02 09:04:20.88', NULL);
+INSERT INTO "public"."Menu" VALUES ('18cf7039-a676-4510-8364-033fa086fdfd', '消息公告详情', 'MENU', '03404a66-50aa-4b21-8c93-9dcddaeffdb7', 'administrative_message-detail', '/administrative/message-detail/:id', 'view.administrative_message-detail', '{"order": 0, "title": "administrative_message-detail", "i18nKey": "route.administrative_message-detail", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": true}', 1, NULL, '2024-09-03 09:32:36.508', '2024-09-04 01:50:07.801', NULL);
+INSERT INTO "public"."Menu" VALUES ('74ca9688-7700-4322-b36f-e1180c5b996b', '消息公告', 'MENU', '03404a66-50aa-4b21-8c93-9dcddaeffdb7', 'administrative_message', '/administrative/message', 'view.administrative_message', '{"icon": "ri:notification-line", "order": 0, "title": "administrative_message", "i18nKey": "route.administrative_message", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 1, NULL, '2024-09-02 08:38:37.368', '2024-09-04 02:16:34.082', NULL);
+INSERT INTO "public"."Menu" VALUES ('2e7aa93e-978c-42e3-aef3-49ec2c7fa183', '角色管理', 'MENU', '572c5097-d28f-48b4-899d-3aaf46b8d668', 'system-manage_role-manage', '/system-manage/role-manage', 'view.system-manage_role-manage', '{"icon": "carbon:user-role", "order": 0, "title": "system-manage_role-manage", "i18nKey": "route.system-manage_role-manage", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 3, NULL, '2024-08-22 08:30:20.282', '2024-09-04 02:18:02.508', NULL);
+INSERT INTO "public"."Menu" VALUES ('881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', '功能页', 'DIRECTORY', NULL, 'features', '/features', 'layout.base', '{"icon": "ri:flower-line", "order": 4, "title": "features", "i18nKey": "route.features", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 4, NULL, '2024-09-10 02:24:51.734', '2024-09-10 02:24:51.734', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('df07b7c5-a08e-4404-809f-0e4315859c9e', 'Nest.js', 'MENU', '3024936c-5e4f-4b0a-a5a8-6360d8294987', 'document_nest', '/document/nest', 'view.iframe-page', '{"href": "https://nestjs.com/", "icon": "logos:nestjs", "order": 1, "title": "document_nest", "i18nKey": "route.document_nest", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 2, NULL, '2024-09-09 08:45:56.931', '2024-09-09 08:46:52.274', NULL);
+INSERT INTO "public"."Menu" VALUES ('6df447b0-d2c2-47a2-afd0-db418db85e76', 'Ant Design Vue', 'MENU', '3024936c-5e4f-4b0a-a5a8-6360d8294987', 'document_antd', '/document/antd', 'view.iframe-page', '{"href": "https://www.antdv.com/", "icon": "logos:ant-design", "order": 2, "title": "document_antd", "i18nKey": "route.document_antd", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 3, NULL, '2024-09-09 08:50:47.598', '2024-09-09 08:50:47.598', NULL);
+INSERT INTO "public"."Menu" VALUES ('86714c51-fce0-498d-9b4f-32fd00ea26a0', 'UnoCSS', 'MENU', '3024936c-5e4f-4b0a-a5a8-6360d8294987', 'document_unocss', '/document/unocss', 'view.iframe-page', '{"href": "https://unocss.dev/", "icon": "logos:unocss", "order": 3, "title": "document_unocss", "i18nKey": "route.document_unocss", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 4, NULL, '2024-09-09 08:51:59.957', '2024-09-09 08:51:59.957', NULL);
+INSERT INTO "public"."Menu" VALUES ('e38ca869-3931-427b-9f19-724416354d24', 'SoybeanAdmin', 'MENU', '3024936c-5e4f-4b0a-a5a8-6360d8294987', 'document_soybean', '/document/soybean', 'view.iframe-page', '{"order": 0, "title": "document_soybean", "i18nKey": "route.document_soybean", "constant": false, "multiTab": false, "keepAlive": false, "localIcon": "soybean", "hideInMenu": false}', 1, NULL, '2024-09-09 09:39:31.997', '2024-09-09 09:40:40.345', '{"url": "https://docs.soybeanjs.cn/zh"}');
+INSERT INTO "public"."Menu" VALUES ('63183e8c-0c27-4642-b783-53290cc7e957', 'Vue3', 'MENU', '3024936c-5e4f-4b0a-a5a8-6360d8294987', 'document_vue', '/document/vue', 'view.iframe-page', '{"href": "https://cn.vuejs.org/", "icon": "logos:vue", "order": 0, "title": "document_vue", "i18nKey": "route.document_vue", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 1, NULL, '2024-09-09 08:34:54.629', '2024-09-09 09:27:10.771', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('3024936c-5e4f-4b0a-a5a8-6360d8294987', '技术文档', 'DIRECTORY', NULL, 'document', '/document', 'layout.base', '{"icon": "mdi:file-document-multiple-outline", "order": 4, "title": "document", "i18nKey": "route.document", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 4, NULL, '2024-09-09 08:29:29.561', '2024-09-10 02:16:01.623', '{}');
+INSERT INTO "public"."Menu" VALUES ('3bceaa2a-4444-4593-8cf1-acf55ee208bf', '验证码', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_captcha', '/features/captcha', 'view.features_captcha', '{"icon": "ri:terminal-box-line", "order": 0, "title": "features_captcha", "i18nKey": "route.features_captcha", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 1, NULL, '2024-09-10 02:28:31.168', '2024-09-10 02:28:31.168', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('d62fde7d-061a-4134-a1a5-88d084299852', '组织架构', 'MENU', '03404a66-50aa-4b21-8c93-9dcddaeffdb7', 'administrative_framework', '/administrative/framework', 'view.administrative_framework', '{"icon": "ri:organization-chart", "order": 1, "title": "administrative_framework", "i18nKey": "route.administrative_framework", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 1, NULL, '2024-09-14 03:36:16.8', '2024-09-14 03:38:34.886', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('ca0a8df9-7daa-4abf-b9dc-9e3f15bed7c4', '打印', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_print', '/features/print', 'view.features_print', '{"icon": "ri:printer-line", "order": 1, "title": "features_print", "i18nKey": "route.features_print", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 2, NULL, '2024-09-14 09:45:34.084', '2024-09-14 09:57:00.156', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('e648628c-e4f3-4abe-a3d6-452b10dd308f', '拾色器', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_pickr', '/features/pickr', 'view.features_pickr', '{"icon": "ri:color-filter-line", "order": 2, "title": "features_pickr", "i18nKey": "route.features_pickr", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 3, NULL, '2024-09-19 01:12:43.102', '2024-09-19 01:12:43.102', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('f7650658-054e-4dca-8fba-92ffa2421f9d', '甘特图', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_gantt', '/features/gantt', 'view.features_gantt', '{"icon": "fa6-solid:chart-gantt", "order": 3, "title": "features_gantt", "i18nKey": "route.features_gantt", "constant": false, "multiTab": false, "keepAlive": true, "hideInMenu": false}', 4, NULL, '2024-09-19 06:52:16.933', '2024-09-19 06:52:16.933', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('fa772008-e045-479b-9d7e-09c04b584277', '图片预览', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_viewer', '/features/viewer', 'view.features_viewer', '{"icon": "ri:image-line", "order": 4, "title": "features_viewer", "i18nKey": "route.features_viewer", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 5, NULL, '2024-09-19 08:30:24.502', '2024-09-19 08:30:24.502', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('c6d8811b-1f1d-46dd-9b29-da46b2278a48', '自定义Vue指令', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_vue-directive', '/features/vue-directive', 'view.features_vue-directive', '{"icon": "ri:command-line", "order": 5, "title": "features_vue-directive", "i18nKey": "route.features_vue-directive", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 6, NULL, '2024-09-19 10:12:57.26', '2024-09-19 10:12:57.26', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('0f6fcc34-8913-47a7-8b28-0c526a22b947', '懒加载', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_lazyload', '/features/lazyload', 'view.features_lazyload', '{"icon": "ri:image-add-line", "order": 6, "title": "features_lazyload", "i18nKey": "route.features_lazyload", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 7, NULL, '2024-09-20 07:25:06.294', '2024-09-20 07:25:06.294', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('a9a40b3f-a86a-4d47-be45-fda5e5bcfaf8', '图片取色盘', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_colorthief', '/features/colorthief', 'view.features_colorthief', '{"icon": "ri:palette-line", "order": 7, "title": "features_colorthief", "i18nKey": "route.features_colorthief", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 8, NULL, '2024-09-20 09:28:35.305', '2024-09-20 09:28:35.305', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('891b01b1-bd1b-4caf-93b2-f7dadd7d2b4b', '系统级取色器', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_eye-dropper', '/features/eye-dropper', 'view.features_eye-dropper', '{"icon": "ri:dropper-line", "order": 8, "title": "features_eye-dropper", "i18nKey": "route.features_eye-dropper", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 9, NULL, '2024-09-23 06:06:37.493', '2024-09-23 06:06:37.493', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('8d3e24e9-fcac-42a8-b1b8-d26d71d06985', '文件预览', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_vue-office', '/features/vue-office', 'view.features_vue-office', '{"icon": "ri:file-excel-2-line", "order": 9, "title": "features_vue-office", "i18nKey": "route.features_vue-office", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 10, NULL, '2024-09-23 07:41:29.012', '2024-09-23 07:41:29.012', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('2a784982-3f4e-4fea-a44e-ab9f7aa302f3', '流程图', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_flow', '/features/flow', 'view.features_flow', '{"icon": "ri:flow-chart", "order": 10, "title": "features_flow", "i18nKey": "route.features_flow", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 11, NULL, '2024-09-25 01:35:16.337', '2024-09-25 01:35:16.337', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('240ed870-775b-42d4-abb3-5d915df5c57f', '瀑布流', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_waterfall', '/features/waterfall', 'view.features_waterfall', '{"icon": "icon-park-outline:waterfalls-h", "order": 11, "title": "features_waterfall", "i18nKey": "route.features_waterfall", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 12, NULL, '2024-09-26 05:43:14.15', '2024-09-26 05:43:14.15', '{"url": ""}');
+INSERT INTO "public"."Menu" VALUES ('7e88d5a1-0517-49ac-b476-f8da0dfa1ef7', 'Swiper', 'MENU', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', 'features_swiper', '/features/swiper', 'view.features_swiper', '{"icon": "simple-icons:swiper", "order": 12, "title": "features_swiper", "i18nKey": "route.features_swiper", "constant": false, "multiTab": false, "keepAlive": false, "hideInMenu": false}', 13, NULL, '2024-09-26 12:10:27.649', '2024-09-26 12:10:27.649', '{"url": ""}');
+
+-- ----------------------------
+-- Indexes structure for table Menu
+-- ----------------------------
+CREATE UNIQUE INDEX "Menu_name_key" ON "public"."Menu" USING btree (
+  "name" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
+);
+CREATE UNIQUE INDEX "Menu_path_key" ON "public"."Menu" USING btree (
+  "path" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
+);
+CREATE UNIQUE INDEX "Menu_permission_key" ON "public"."Menu" USING btree (
+  "permission" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
+);
+
+-- ----------------------------
+-- Primary Key structure for table Menu
+-- ----------------------------
+ALTER TABLE "public"."Menu" ADD CONSTRAINT "Menu_pkey" PRIMARY KEY ("id");
+
+-- ----------------------------
+-- Foreign Keys structure for table Menu
+-- ----------------------------
+ALTER TABLE "public"."Menu" ADD CONSTRAINT "Menu_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "public"."Menu" ("id") ON DELETE SET NULL ON UPDATE CASCADE;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 37 - 0
postgreSQL/Message.sql


+ 62 - 0
postgreSQL/MessageRead.sql

@@ -0,0 +1,62 @@
+/*
+ Navicat Premium Dump SQL
+
+ Source Server         : postgreSQL
+ Source Server Type    : PostgreSQL
+ Source Server Version : 160003 (160003)
+ Source Host           : localhost:5432
+ Source Catalog        : vue3-admin
+ Source Schema         : public
+
+ Target Server Type    : PostgreSQL
+ Target Server Version : 160003 (160003)
+ File Encoding         : 65001
+
+ Date: 31/10/2024 10:17:09
+*/
+
+
+-- ----------------------------
+-- Table structure for MessageRead
+-- ----------------------------
+DROP TABLE IF EXISTS "public"."MessageRead";
+CREATE TABLE "public"."MessageRead" (
+  "id" text COLLATE "pg_catalog"."default" NOT NULL,
+  "messageId" text COLLATE "pg_catalog"."default" NOT NULL,
+  "userId" text COLLATE "pg_catalog"."default" NOT NULL,
+  "createdAt" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP
+)
+;
+
+-- ----------------------------
+-- Records of MessageRead
+-- ----------------------------
+INSERT INTO "public"."MessageRead" VALUES ('e894e6bf-3dd2-45bf-b736-e66169d83add', 'b64c3c94-5312-45f2-aa8f-fca11a04263a', 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f', '2024-09-04 02:15:57.743');
+INSERT INTO "public"."MessageRead" VALUES ('c218f953-87f2-4cc9-a552-e80a64b2ebfa', '2215f10b-ca4f-4a73-b78b-a14a6ae4d52f', 'ea35984a-34f6-4da3-9f50-314f4b719ea6', '2024-09-04 05:53:47.778');
+INSERT INTO "public"."MessageRead" VALUES ('472116d6-5059-4201-9d09-420d17b3f49f', 'e9016a44-3ef8-4cac-8dcd-881a74559fba', 'ea35984a-34f6-4da3-9f50-314f4b719ea6', '2024-09-04 05:54:33.608');
+INSERT INTO "public"."MessageRead" VALUES ('705a6c64-eee9-4e3c-b867-b4fbfb87d854', 'e9016a44-3ef8-4cac-8dcd-881a74559fba', 'b485e3c1-0790-4007-adef-849537c291f5', '2024-09-04 05:56:20.796');
+INSERT INTO "public"."MessageRead" VALUES ('e762f6f0-8f3c-4769-8505-21b9772e0989', 'e9016a44-3ef8-4cac-8dcd-881a74559fba', 'bf9c32dc-2363-4a31-9e7f-74544f7d04a4', '2024-09-04 06:05:15.354');
+INSERT INTO "public"."MessageRead" VALUES ('dafa0711-0e2f-480c-957a-ad2bebc03a80', 'e9016a44-3ef8-4cac-8dcd-881a74559fba', 'c698c8e8-3aa0-4dec-b1cd-7d37660d1519', '2024-09-04 06:13:22.907');
+INSERT INTO "public"."MessageRead" VALUES ('b60e0224-750c-442e-9a2d-5b6184b74b28', '3ee060d0-7975-4cd5-bb7d-4f884d7824ba', 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f', '2024-09-04 06:15:40.04');
+INSERT INTO "public"."MessageRead" VALUES ('4f3d2cd5-0b90-4871-bc29-b634494fdb2e', '3ee060d0-7975-4cd5-bb7d-4f884d7824ba', 'c698c8e8-3aa0-4dec-b1cd-7d37660d1519', '2024-09-04 06:16:08.858');
+INSERT INTO "public"."MessageRead" VALUES ('3e5ca7b4-f6bc-4fc1-a33d-96a9ba76fb4c', '2215f10b-ca4f-4a73-b78b-a14a6ae4d52f', 'ba54e74c-86cb-4bfa-a0bc-71813175de9e', '2024-09-04 06:27:34.042');
+INSERT INTO "public"."MessageRead" VALUES ('68e203e5-4902-4aaa-a56e-2434619df84e', 'e9016a44-3ef8-4cac-8dcd-881a74559fba', 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f', '2024-09-04 06:29:25.511');
+INSERT INTO "public"."MessageRead" VALUES ('34b59c85-bc50-4e36-8e77-50505bf720d8', '2215f10b-ca4f-4a73-b78b-a14a6ae4d52f', 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f', '2024-09-04 06:32:27.602');
+INSERT INTO "public"."MessageRead" VALUES ('239e152f-eb37-4e8b-a1e1-fb216b57c6af', '2215f10b-ca4f-4a73-b78b-a14a6ae4d52f', 'b485e3c1-0790-4007-adef-849537c291f5', '2024-09-04 06:49:39.364');
+INSERT INTO "public"."MessageRead" VALUES ('e9927102-4ead-4994-88e6-9627f06fe894', '2215f10b-ca4f-4a73-b78b-a14a6ae4d52f', 'b62c0c5a-ac9f-4d7d-863c-fbfa148bbc4c', '2024-09-04 06:49:59.016');
+INSERT INTO "public"."MessageRead" VALUES ('1494516c-5193-4e4f-9f0e-c60493054581', '2215f10b-ca4f-4a73-b78b-a14a6ae4d52f', 'bf9c32dc-2363-4a31-9e7f-74544f7d04a4', '2024-09-04 06:50:13.943');
+INSERT INTO "public"."MessageRead" VALUES ('9a1c750a-2a15-498e-b4c4-a486f7258ae0', '49c29eb9-887d-4aad-a77b-4a72b81fcfd5', 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f', '2024-09-06 10:15:28.634');
+INSERT INTO "public"."MessageRead" VALUES ('290f44b4-c702-4ac0-9f90-a3865cfba9a3', '805818b4-683b-41b7-a301-7843a1455776', 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f', '2024-09-06 10:16:00.541');
+INSERT INTO "public"."MessageRead" VALUES ('c605621b-dc23-4471-926b-e016f29e33b1', '1ed975b1-3b92-4496-955c-883c6f8521bf', 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f', '2024-09-06 10:17:00.587');
+INSERT INTO "public"."MessageRead" VALUES ('c88b2664-e589-46bb-a3d5-0bf40561210a', '70412167-ef80-49a3-b764-8b08841fcbeb', 'bf9c32dc-2363-4a31-9e7f-74544f7d04a4', '2024-09-06 10:25:48.045');
+
+-- ----------------------------
+-- Primary Key structure for table MessageRead
+-- ----------------------------
+ALTER TABLE "public"."MessageRead" ADD CONSTRAINT "MessageRead_pkey" PRIMARY KEY ("id");
+
+-- ----------------------------
+-- Foreign Keys structure for table MessageRead
+-- ----------------------------
+ALTER TABLE "public"."MessageRead" ADD CONSTRAINT "MessageRead_messageId_fkey" FOREIGN KEY ("messageId") REFERENCES "public"."Message" ("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+ALTER TABLE "public"."MessageRead" ADD CONSTRAINT "MessageRead_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE;

+ 86 - 0
postgreSQL/Organization.sql

@@ -0,0 +1,86 @@
+/*
+ Navicat Premium Dump SQL
+
+ Source Server         : postgreSQL
+ Source Server Type    : PostgreSQL
+ Source Server Version : 160003 (160003)
+ Source Host           : localhost:5432
+ Source Catalog        : vue3-admin
+ Source Schema         : public
+
+ Target Server Type    : PostgreSQL
+ Target Server Version : 160003 (160003)
+ File Encoding         : 65001
+
+ Date: 31/10/2024 10:17:13
+*/
+
+
+-- ----------------------------
+-- Table structure for Organization
+-- ----------------------------
+DROP TABLE IF EXISTS "public"."Organization";
+CREATE TABLE "public"."Organization" (
+  "id" text COLLATE "pg_catalog"."default" NOT NULL,
+  "name" text COLLATE "pg_catalog"."default" NOT NULL,
+  "code" text COLLATE "pg_catalog"."default" NOT NULL,
+  "parentId" text COLLATE "pg_catalog"."default",
+  "sort" int4 NOT NULL,
+  "description" text COLLATE "pg_catalog"."default",
+  "icon" text COLLATE "pg_catalog"."default",
+  "createdAt" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  "updatedAt" timestamp(3) NOT NULL
+)
+;
+
+-- ----------------------------
+-- Records of Organization
+-- ----------------------------
+INSERT INTO "public"."Organization" VALUES ('0da77343-0747-42fe-beff-25ee98bc7a88', '公司总部', 'HB_001', NULL, 1, '', NULL, '2024-07-15 07:50:29.916', '2024-07-15 07:50:29.916');
+INSERT INTO "public"."Organization" VALUES ('b924df00-77ed-49b7-a8b4-181f0b259c18', '深圳分公司', 'SZ_001', '0da77343-0747-42fe-beff-25ee98bc7a88', 1, '', NULL, '2024-07-15 07:51:09.095', '2024-07-15 07:51:09.095');
+INSERT INTO "public"."Organization" VALUES ('a12e5511-06f9-42e4-b8fb-816b8d5e346f', '广州分公司', 'GZ_001', '0da77343-0747-42fe-beff-25ee98bc7a88', 1, '', NULL, '2024-07-15 07:51:42.349', '2024-07-15 07:51:42.349');
+INSERT INTO "public"."Organization" VALUES ('68c4ac85-3f4a-4ca0-9112-562e91a1d6a2', '北京分公司', 'BJ_001', '0da77343-0747-42fe-beff-25ee98bc7a88', 1, '', NULL, '2024-07-15 07:52:09.127', '2024-07-15 07:52:09.127');
+INSERT INTO "public"."Organization" VALUES ('a8c5d1e8-72a2-4815-9842-7a31bcd82917', '上海分公司', 'SH_001', '0da77343-0747-42fe-beff-25ee98bc7a88', 1, '', NULL, '2024-07-15 07:52:23.694', '2024-07-15 07:52:23.694');
+INSERT INTO "public"."Organization" VALUES ('3bc8ec43-8441-4a4a-9935-5e5baf09d62b', '福田分部', 'SZ_002', 'b924df00-77ed-49b7-a8b4-181f0b259c18', 1, '', NULL, '2024-07-15 07:52:43.722', '2024-07-15 07:52:43.722');
+INSERT INTO "public"."Organization" VALUES ('3348943f-c85a-43ce-ba68-71516df3a28d', '南山分部', 'SZ_003', 'b924df00-77ed-49b7-a8b4-181f0b259c18', 1, '', NULL, '2024-07-15 07:53:06.458', '2024-07-15 07:53:06.458');
+INSERT INTO "public"."Organization" VALUES ('60563a3f-b2b0-4a3a-9525-8676ba3ac9eb', '罗湖分部', 'SZ_004', 'b924df00-77ed-49b7-a8b4-181f0b259c18', 1, '', NULL, '2024-07-15 07:53:32.309', '2024-07-15 07:53:32.309');
+INSERT INTO "public"."Organization" VALUES ('61a688b2-789c-4d2f-a149-46542bae0547', '天河分部', 'GZ_002', 'a12e5511-06f9-42e4-b8fb-816b8d5e346f', 1, '', NULL, '2024-07-15 07:53:51.31', '2024-07-15 07:53:51.31');
+INSERT INTO "public"."Organization" VALUES ('7657fca9-acb5-42a9-ab6a-782d34ab9b62', '白云分部', 'GZ_003', 'a12e5511-06f9-42e4-b8fb-816b8d5e346f', 1, '', NULL, '2024-07-15 07:54:06.75', '2024-07-15 07:54:06.75');
+INSERT INTO "public"."Organization" VALUES ('6cabf39a-6b5a-4ef1-b8ba-59d2ac7b6a1a', '黄埔分部', 'GZ_004', 'a12e5511-06f9-42e4-b8fb-816b8d5e346f', 1, '', NULL, '2024-07-15 07:54:25.426', '2024-07-15 07:54:25.426');
+INSERT INTO "public"."Organization" VALUES ('6dee4d4f-d9f0-41fe-bae3-febd45aa9b3e', '浦东新区分部', 'SH_002', 'a8c5d1e8-72a2-4815-9842-7a31bcd82917', 1, '', NULL, '2024-07-15 07:55:10.858', '2024-07-15 07:55:10.858');
+INSERT INTO "public"."Organization" VALUES ('40129577-049f-4f40-9e2e-2c1188e4695f', '徐汇区', 'SH_003', 'a8c5d1e8-72a2-4815-9842-7a31bcd82917', 1, '', NULL, '2024-07-15 07:55:31.164', '2024-07-15 07:55:31.164');
+INSERT INTO "public"."Organization" VALUES ('4a89a957-9c4f-45da-a3c9-20334a2b3d14', '长宁区', 'SH_004', 'a8c5d1e8-72a2-4815-9842-7a31bcd82917', 1, '', NULL, '2024-07-15 07:55:52.348', '2024-07-15 07:55:52.348');
+INSERT INTO "public"."Organization" VALUES ('896c6abe-3007-4fc6-a29d-abffcbbd38fb', '朝阳区分部', 'BJ_002', '68c4ac85-3f4a-4ca0-9112-562e91a1d6a2', 1, '', NULL, '2024-07-15 07:57:23.174', '2024-07-15 07:57:23.174');
+INSERT INTO "public"."Organization" VALUES ('6bd10709-d784-42fa-ba93-447707e567c2', '海淀区分部', 'BJ_003', '68c4ac85-3f4a-4ca0-9112-562e91a1d6a2', 1, '', NULL, '2024-07-15 07:57:48.801', '2024-07-15 07:57:48.801');
+INSERT INTO "public"."Organization" VALUES ('f45cd48b-e703-49db-91be-ae7f594e73e0', '阿里巴巴', 'ALI_000', NULL, 1, '阿里巴巴集团由曾担任英语教师的马云为首的18人,于1999年在中国杭州创立。从一开始,所有创始人就深信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。自推出让中国的小型出口商、制造商及创业者接触全球买家的首个网站以来,阿里巴巴集团不断成长,成为了网上及移动商务的全球领导者。', 'simple-icons:alibabadotcom', '2024-07-15 07:59:08.613', '2024-07-15 07:59:08.613');
+INSERT INTO "public"."Organization" VALUES ('9382c3d0-42ef-496b-961f-f0bcee6edfbf', '支付宝', 'ALI_002', 'f45cd48b-e703-49db-91be-ae7f594e73e0', 1, '支付宝(Alipay)是蚂蚁科技集团股份有限公司旗下业务,成立于2004年,是中国第三方支付开放平台,是当下世界上流行的网络银行和网络支付形式之一。', 'ri:alipay-fill', '2024-07-15 07:59:53.677', '2024-07-15 07:59:53.677');
+INSERT INTO "public"."Organization" VALUES ('ed09ac6d-d9d8-456a-ab93-e4e047a9048d', '钉钉', 'ALI_003', 'f45cd48b-e703-49db-91be-ae7f594e73e0', 1, '钉钉(Ding Talk)是阿里巴巴集团打造的企业级智能移动办公平台,是数字经济时代的企业组织协同办公和应用开发平台。', 'ri:dingding-fill', '2024-07-15 08:00:44.777', '2024-07-15 08:00:44.777');
+INSERT INTO "public"."Organization" VALUES ('460e32b7-6c69-47b2-ab01-30268952f52e', '淘宝', 'ALI_005', 'f45cd48b-e703-49db-91be-ae7f594e73e0', 1, '淘宝网是亚太地区较大的网络零售、商圈,由阿里巴巴集团在2003年5月创立。淘宝网是中国深受欢迎的网购零售平台,拥有近5亿的注册用户数,每天有超过6000万的固定访客,同时每天的在线商品数已经超过了8亿件,平均每分钟售出4.8万件商品。', 'ri:taobao-fill', '2024-07-15 08:01:53.37', '2024-07-15 08:01:53.37');
+INSERT INTO "public"."Organization" VALUES ('e5f4ae69-633b-48ff-8ef1-b92597f2a26c', '字节跳动', 'BYTE_001', NULL, 1, '北京抖音信息服务有限公司,成立于2012年3月9日,2023年收入8635亿元。 地址位于北京市海淀区北三环西路甲23号院1号楼2层222。公司以建设“全球创作与交流平台”为愿景。字节跳动的全球化布局始于2015年,“技术出海”是字节跳动全球化发展的核心战略,其旗下产品有今日头条、西瓜视频、抖音、头条百科、皮皮虾、懂车帝、悟空问答等。', 'simple-icons:bytedance', '2024-07-15 08:03:11.493', '2024-07-15 08:03:11.493');
+INSERT INTO "public"."Organization" VALUES ('2eaab2c3-4872-49af-b647-78ba9c120df8', '抖音', 'BYTE_002', 'e5f4ae69-633b-48ff-8ef1-b92597f2a26c', 1, '抖音让每一个人看见并连接更大的世界,鼓励表达、沟通和记录,激发创造,丰富人们的精神世界,让现实生活更美好。', 'ri:tiktok-fill', '2024-07-15 08:04:44.402', '2024-07-15 08:04:44.402');
+INSERT INTO "public"."Organization" VALUES ('30b5bef3-1c1b-4c86-afb1-353d0c7a696f', '今日头条', 'BYTE_003', 'e5f4ae69-633b-48ff-8ef1-b92597f2a26c', 1, '今日头条是一个通用信息平台,致力于连接人与信息,让优质丰富的信息得到高效精准的分发,促使信息创造价值。 今日头条目前拥有推荐引擎、搜索引擎、关注订阅和内容运营等多种分发方式,囊括图文、视频、问答、微头条、专栏、小说、直播、音频和小程序等多种内容体裁,并涵盖科技、体育、健康、美食、教育、三农、国风等超过100个内容领域。', 'icon-park-solid:jinritoutiao', '2024-07-15 08:05:42.858', '2024-07-15 08:05:42.858');
+INSERT INTO "public"."Organization" VALUES ('8233a4de-02f8-49d8-85e8-5a92fd8552e0', '西瓜视频', 'BYTE_004', 'e5f4ae69-633b-48ff-8ef1-b92597f2a26c', 1, '西瓜视频是国内领先的 PUGC 视频平台,它通过个性化推荐,为不同人群提供优质内容,同时鼓励多样化创作,帮助人们轻松地向全世界分享视频作品。', 'icon-park-solid:xigua', '2024-07-15 08:06:23.101', '2024-07-15 08:06:23.101');
+INSERT INTO "public"."Organization" VALUES ('32cab8f0-13df-4876-83c5-86089390dbb7', '腾讯控股', 'TC_001', NULL, 1, '腾讯于1998年11月成立,是一家互联网公司,通过技术丰富互联网用户的生活,助力企业数字化升级。我们的使命是“用户为本 科技向善”。', '', '2024-07-15 08:10:03.173', '2024-07-15 08:13:33.775');
+INSERT INTO "public"."Organization" VALUES ('d21a1820-d650-4eaa-8b83-ba0fed7febe7', '微信', 'TC_002', '32cab8f0-13df-4876-83c5-86089390dbb7', 1, '微信(WeChat)是腾讯公司于2011年1月21日推出的一个为智能终端提供即时通讯服务的免费应用程序,由张小龙所带领的腾讯广州研发中心产品团队打造。', 'ri:wechat-fill', '2024-07-15 08:14:30.153', '2024-07-15 08:14:30.153');
+INSERT INTO "public"."Organization" VALUES ('038d606e-304d-4cff-bb09-70f5be4a8f19', 'QQ', 'TC_003', '32cab8f0-13df-4876-83c5-86089390dbb7', 1, 'QQ(腾讯QQ),是腾讯公司推出的一款基于互联网即时通信软件。腾讯QQ支持在线聊天、视频通话、点对点断点续传文件、共享文件、网络硬盘、自定义面板、QQ邮箱等多种功能,并可与多种通讯终端相连。', 'ri:qq-fill', '2024-07-15 08:15:21.584', '2024-07-15 08:15:21.584');
+INSERT INTO "public"."Organization" VALUES ('38c80d63-c18e-4dc4-9b36-f962146af156', '阿里云', 'ALI_004', 'f45cd48b-e703-49db-91be-ae7f594e73e0', 1, '阿里云创立于2009年,是全球领先的云计算及人工智能科技公司,致力于以在线公共服务的方式,提供安全、可靠的计算和数据处理能力,让计算和人工智能成为普惠科技。', 'ri:alibaba-cloud-fill', '2024-07-15 08:01:17.818', '2024-07-17 02:38:12.852');
+
+-- ----------------------------
+-- Indexes structure for table Organization
+-- ----------------------------
+CREATE UNIQUE INDEX "Organization_code_key" ON "public"."Organization" USING btree (
+  "code" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
+);
+CREATE UNIQUE INDEX "Organization_name_key" ON "public"."Organization" USING btree (
+  "name" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
+);
+
+-- ----------------------------
+-- Primary Key structure for table Organization
+-- ----------------------------
+ALTER TABLE "public"."Organization" ADD CONSTRAINT "Organization_pkey" PRIMARY KEY ("id");
+
+-- ----------------------------
+-- Foreign Keys structure for table Organization
+-- ----------------------------
+ALTER TABLE "public"."Organization" ADD CONSTRAINT "Organization_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "public"."Organization" ("id") ON DELETE SET NULL ON UPDATE CASCADE;

+ 187 - 0
postgreSQL/Permission.sql

@@ -0,0 +1,187 @@
+/*
+ Navicat Premium Dump SQL
+
+ Source Server         : postgreSQL
+ Source Server Type    : PostgreSQL
+ Source Server Version : 160003 (160003)
+ Source Host           : localhost:5432
+ Source Catalog        : vue3-admin
+ Source Schema         : public
+
+ Target Server Type    : PostgreSQL
+ Target Server Version : 160003 (160003)
+ File Encoding         : 65001
+
+ Date: 31/10/2024 10:17:18
+*/
+
+
+-- ----------------------------
+-- Table structure for Permission
+-- ----------------------------
+DROP TABLE IF EXISTS "public"."Permission";
+CREATE TABLE "public"."Permission" (
+  "id" text COLLATE "pg_catalog"."default" NOT NULL,
+  "roleId" text COLLATE "pg_catalog"."default" NOT NULL,
+  "menuId" text COLLATE "pg_catalog"."default" NOT NULL,
+  "createdAt" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP
+)
+;
+
+-- ----------------------------
+-- Records of Permission
+-- ----------------------------
+INSERT INTO "public"."Permission" VALUES ('3920c9bc-ee77-42b8-b66a-88a1c4920366', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', '8f16a2cd-b613-4419-bfa5-996f16beaa6a', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('111cc74e-f92b-4228-bce6-35cf3a4ba686', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', '18cf7039-a676-4510-8364-033fa086fdfd', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('26a32aa1-80fa-452e-b872-c65cc9a419b7', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', '45d1f4ea-a1e5-4e48-b6a7-141e1fa63b67', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('d89b0e72-1577-4de1-ad84-d51400a907b1', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', 'db837491-6a97-412d-8668-32de8e286390', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('4d9fe625-8ec3-44c4-9493-8408eec6f80f', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', 'ad167628-1055-470c-90ba-f401c4edc621', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('089a0922-71e4-4d30-8ff0-47618e09a630', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', 'e02f4271-4f9b-47e5-a76f-040db8404bd2', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('7afdacc6-10dd-47a1-a427-bb85630582c0', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', 'fd9ac9a5-be38-426c-b38a-8bda75420ffc', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('1366d2f6-27eb-4a5e-878f-9d994b22b7b2', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', '76402592-28e6-4575-9454-b38133652fa8', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('d128e74d-13c0-4c65-85b3-0fa43c1fe1eb', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', 'c4bb98dd-e417-438b-8fe5-7b27e2921e72', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('67840934-2ec6-4e41-b45d-8941fd7a8e04', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', '8be52db9-1856-4f14-8b2f-12c51ba45a3e', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('7bc31744-10c4-4993-bfc0-f952d3650d2d', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', '48d6f0b5-5b11-422c-bee9-d1caa8447966', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('b2584da3-685c-400c-bc88-005888550fed', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', '4918cc69-4050-4929-9113-e5cb7e67b848', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('82a35dfd-37f0-41db-a389-cb4b4688bf13', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', 'db9d9316-ad43-41f2-9060-f6f55a6d0fd2', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('155f6641-b285-4d3b-94ac-53fd6f6d5e45', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', '0916a1b8-bf6f-4732-9c3c-c0b834c9e1cc', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('c8e614d5-db20-41b6-93f6-079cb1cad669', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', '74ca9688-7700-4322-b36f-e1180c5b996b', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('c7de100d-9051-48b1-9380-89ae17fd6d82', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', 'dea4e038-592f-4532-ac86-c7de25a3416c', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('1a1e2658-1f1b-49d4-b0ac-dba0ca7b31a1', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', '5dc9be35-dfad-493e-99c4-fdca4ddff1f5', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('872cdd99-602d-4ea5-b627-42ae343400a7', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', '03404a66-50aa-4b21-8c93-9dcddaeffdb7', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('cf6f807a-a6ac-4037-8dbd-8a4758197778', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', 'd62fde7d-061a-4134-a1a5-88d084299852', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Permission" VALUES ('725ce1e3-cd78-4379-904f-6e5ca56294bc', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '240ed870-775b-42d4-abb3-5d915df5c57f', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('1ede724b-8564-4513-b422-02834af960ac', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'a9a40b3f-a86a-4d47-be45-fda5e5bcfaf8', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('bb6c4843-9ae6-4e8e-ad14-732380b0256f', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '891b01b1-bd1b-4caf-93b2-f7dadd7d2b4b', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('5e8ab42b-41a9-4003-a3cb-89b2f461f5fa', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '8d3e24e9-fcac-42a8-b1b8-d26d71d06985', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('6201a214-d08a-4758-8dd8-d168e5e50153', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'c6d8811b-1f1d-46dd-9b29-da46b2278a48', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('d0f19cc4-e097-4c83-8538-b205fc7ba0b0', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'e648628c-e4f3-4abe-a3d6-452b10dd308f', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('bec1569c-2935-4a8a-bd5a-e81831f96c09', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '6b52bc0a-f2b6-4422-8ef8-dde0c5b81f96', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('d6d6a345-811c-4c07-b0fa-b8c87e4dbff1', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '7131adbe-2b2b-4233-ab50-e9ee1859b09b', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('865590e0-d93c-4517-9860-608a82c46df2', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '4bcb5d6b-f876-4e95-8e13-e847bcb18d5d', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('5bae82e3-d389-4dbf-b03e-9af9cce04247', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'e3f98b23-30a9-4b6b-b15c-fe08b13baf5f', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('dd56798b-6858-4d72-a4ef-367cc9cae999', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '52ff7472-67da-4f9b-ba90-ec5468492f32', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('6e0fde5d-6ba0-4796-9eeb-483984f343de', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'f309088f-e63d-48a1-8dce-1b9409dfe0b0', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('dc9c52ef-a21a-44de-8f43-23ba3a226d66', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '848a03e4-25db-41f8-97bf-c154fa160c64', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('609674cf-1578-48b9-ad7b-7ce1b2701f69', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '45d1f4ea-a1e5-4e48-b6a7-141e1fa63b67', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('50b1c8a1-3a71-45fc-8866-6dcd718fec2f', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'db837491-6a97-412d-8668-32de8e286390', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('41b383b9-2b2a-4240-bc3c-0fcaa9cc2ed7', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'ad167628-1055-470c-90ba-f401c4edc621', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('9b307de0-26af-4e40-aec6-cd88278e8302', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'e02f4271-4f9b-47e5-a76f-040db8404bd2', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('f5f36554-f554-444e-894c-20b41caeaf8a', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'fd9ac9a5-be38-426c-b38a-8bda75420ffc', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('434e5721-32a9-4eb7-adfb-a6fcc3a8ee6b', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '76402592-28e6-4575-9454-b38133652fa8', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('1047605c-866e-412e-bd5b-fc3f857be0f5', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'c4bb98dd-e417-438b-8fe5-7b27e2921e72', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('891d9884-e700-4ea4-85b5-7dfb4ed3f3ab', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '8be52db9-1856-4f14-8b2f-12c51ba45a3e', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('534c4674-eb41-496e-abfc-b4acfbf64c54', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '48d6f0b5-5b11-422c-bee9-d1caa8447966', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('b5bb1ee0-9d91-4680-a8d9-89804259e051', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '4918cc69-4050-4929-9113-e5cb7e67b848', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('b7aae08a-da90-4a29-8fd9-9f0ddfa25491', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'db9d9316-ad43-41f2-9060-f6f55a6d0fd2', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('c854c6cf-5059-46b3-94e4-efa6ba5ad6d7', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '0916a1b8-bf6f-4732-9c3c-c0b834c9e1cc', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('d42f3497-7c57-4da4-865c-ba1d068a55c9', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', 'a8304bfd-0b75-4203-aa30-24c0ee98d4f5', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('fb257b39-a4de-4ecb-b58a-b6131f454626', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '7abbee43-cd32-4633-9702-2511eda28357', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('3edeea52-ff9e-4a10-8f37-4c2622bb9e95', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '7131adbe-2b2b-4233-ab50-e9ee1859b09b', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('e3f441e7-53de-4fe7-acee-f3188fddf671', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '4bcb5d6b-f876-4e95-8e13-e847bcb18d5d', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('62b1c717-6cb0-41f9-a988-0be879416f8f', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', 'e3f98b23-30a9-4b6b-b15c-fe08b13baf5f', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('3b9a7166-d49e-4a5b-bf9d-2c71de786077', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', 'f309088f-e63d-48a1-8dce-1b9409dfe0b0', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('488c0309-60fe-4189-afcb-9fbfd6af4eb7', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '848a03e4-25db-41f8-97bf-c154fa160c64', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('ac01c651-ac94-48e2-a7ee-f74fc3bc73e7', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '572c5097-d28f-48b4-899d-3aaf46b8d668', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('0d7477dc-b550-48a1-9c5f-38bd92679880', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '1ee566d9-d5ef-456a-8009-d67bb026b4b0', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('7b2dadb6-9f8b-4770-accf-381855f8962f', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '28a745e9-ff3a-49c2-bebc-e269146652e6', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('45030111-6cd6-49ab-828b-1097a22e7bab', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '2e7aa93e-978c-42e3-aef3-49ec2c7fa183', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('a8ebb9f6-f476-420b-80ec-943d418e34ab', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', 'aaf9caab-e4cc-491c-bf9c-d5fe81b9d867', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('010f0c2c-8b09-4e88-82df-30d4933c0d16', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '18cf7039-a676-4510-8364-033fa086fdfd', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('42cc8832-d061-46f2-a670-5d4b11846877', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '63183e8c-0c27-4642-b783-53290cc7e957', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('6773d139-8927-4e82-8574-4cd9f4652026', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'df07b7c5-a08e-4404-809f-0e4315859c9e', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('d9d986b4-2ac6-4321-9ebe-68ca238668e9', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '6df447b0-d2c2-47a2-afd0-db418db85e76', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('171d8598-5d2c-4079-8768-275c3aa49140', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '86714c51-fce0-498d-9b4f-32fd00ea26a0', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('776c3d2f-c0f3-479d-ac1e-34de379a5c71', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'e38ca869-3931-427b-9f19-724416354d24', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('bffaa2df-3b6a-4f04-8daa-55fa1f3f4297', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '3bceaa2a-4444-4593-8cf1-acf55ee208bf', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('81bea8e4-619a-4c2f-a8e6-848ba4fd5b69', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '4fc642f4-18bb-4b18-980b-7e41e804720c', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('d4bd64d5-90f8-47c0-984b-bfd2ab59b0a8', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '8f16a2cd-b613-4419-bfa5-996f16beaa6a', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('b74cdea8-27d5-4444-b37a-b635a1062f2e', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '4d238c00-d8c0-4ed2-a803-41caf772820e', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('eeff5504-cfb0-44ec-967a-abd571b34b6c', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'e1b37b30-e000-4c24-8976-8c9fa78042b0', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('53a1eb01-06f3-4e87-8d9b-57dc27213a70', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'a66a0e69-cd75-4460-b766-1ad52a82ac10', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('e8c5bccb-a5a4-4dee-b9f4-bfec15c705a2', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'acfd4d4c-4b12-46b9-9a11-e85c2fc8e667', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('c3969c68-c53b-4a74-8878-c519c7622124', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'ea793941-1ca1-4e23-ac0e-784d3a95743a', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('71a1e87a-df80-48e9-9daf-d9615b89296a', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '0c437ad9-c18e-46df-b2c1-c1330601ac3c', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('9c8fa6fa-af45-4d55-be2c-3f580e8f07d6', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '596eba6b-6b80-495a-bf9d-f90fdfb9e49d', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('6c17b698-a3d9-432d-95cb-913e3ee66055', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', 'e1b37b30-e000-4c24-8976-8c9fa78042b0', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('03f5b324-caec-43b0-8815-22492a8d041a', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '0c437ad9-c18e-46df-b2c1-c1330601ac3c', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('59cf91bb-da4d-4bd3-b521-72ead88f6a36', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '9ff718db-c9f9-4fd4-8cc2-d6212b74c336', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('fcbd0d15-f657-48b5-a821-560c2823fb00', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '6b52bc0a-f2b6-4422-8ef8-dde0c5b81f96', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('bfd44238-a8a7-4524-8abe-54cbeb982105', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '52ff7472-67da-4f9b-ba90-ec5468492f32', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('48a9ad44-3d3e-49bd-8a83-63db8cc2fdb9', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '9e378453-357b-4395-a342-d53f98d6db46', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('142ef629-5eec-407f-82a4-d4f5d2a812db', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '37191c9a-19b7-43aa-9ad5-369100f1407c', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('f5381250-1dab-45bc-8c31-3ce4afb328ee', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '61da313d-4b5f-40b4-9bc3-55b57ebf18d1', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('baf9dda3-b933-4860-9836-91e4881fb35e', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '9ff718db-c9f9-4fd4-8cc2-d6212b74c336', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('bcc610e3-9aa9-49e1-a084-7901373b261b', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '3064dd2b-38d6-46ba-965e-21a101da688c', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('aa7ad9d7-6d97-4e5b-b757-9e26567d3c33', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'a8304bfd-0b75-4203-aa30-24c0ee98d4f5', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('c19b3bad-7a54-4382-84af-f54ed3fafcd3', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '7abbee43-cd32-4633-9702-2511eda28357', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('1f884e32-15dc-44b4-a1e1-db176363b7c7', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'd62fde7d-061a-4134-a1a5-88d084299852', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('6f968807-01e8-46e1-8f85-28f246a9b091', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'ca0a8df9-7daa-4abf-b9dc-9e3f15bed7c4', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('1171edfe-c3b1-4998-b9a7-7fbd4bcdb6d6', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'f7650658-054e-4dca-8fba-92ffa2421f9d', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('63071bb1-4d14-42c9-846c-a71c44387ece', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'fa772008-e045-479b-9d7e-09c04b584277', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('3703f554-2c08-455c-97bf-ee3dbea93786', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '0f6fcc34-8913-47a7-8b28-0c526a22b947', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('4fe903ec-8a89-40fe-bb92-92d16a89d40a', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '2a784982-3f4e-4fea-a44e-ab9f7aa302f3', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('cbc845ec-9cc9-403a-8c56-a35d670584cf', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '74ca9688-7700-4322-b36f-e1180c5b996b', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('450c1357-22fa-4ecc-9b07-2ad18270921b', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'dea4e038-592f-4532-ac86-c7de25a3416c', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('9a9439af-cd78-4f62-8c74-41a41b32a991', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '5dc9be35-dfad-493e-99c4-fdca4ddff1f5', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('f57aa064-2e96-4ad5-8a63-389a021fae2b', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '1ee566d9-d5ef-456a-8009-d67bb026b4b0', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('50a9f91b-e171-4ccd-8112-3391340d2498', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '28a745e9-ff3a-49c2-bebc-e269146652e6', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('e0aae778-3317-4352-96e9-0247dc0902ca', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '2e7aa93e-978c-42e3-aef3-49ec2c7fa183', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('0a115db5-0957-4b0c-97e6-f2d58a29253e', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'aaf9caab-e4cc-491c-bf9c-d5fe81b9d867', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('17070d4b-b014-4eaa-b738-ce7437df5b0b', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '596eba6b-6b80-495a-bf9d-f90fdfb9e49d', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('c98cf00a-ac86-41f8-893e-cfd64bb9b267', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '03404a66-50aa-4b21-8c93-9dcddaeffdb7', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('03f9b09e-868f-4caf-a5a7-c0d2f2b584b6', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '3024936c-5e4f-4b0a-a5a8-6360d8294987', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('b3e0cb02-f9a9-436c-9535-b9ea7a55b162', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '572c5097-d28f-48b4-899d-3aaf46b8d668', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('eef6a2f8-e1da-4dfa-bb23-91b837743b02', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('f0ef0840-9a97-4600-ad6d-f20585e3a4bd', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '7e88d5a1-0517-49ac-b476-f8da0dfa1ef7', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Permission" VALUES ('0e69a571-a73f-4d5a-b4cf-28506bbcd0d7', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '8f16a2cd-b613-4419-bfa5-996f16beaa6a', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('247ca198-63af-473f-beec-d74a147194cf', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', 'a66a0e69-cd75-4460-b766-1ad52a82ac10', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('1cd75428-3747-40fa-85ce-d04864ddc32b', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', 'acfd4d4c-4b12-46b9-9a11-e85c2fc8e667', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('d0fae29c-1839-40dc-83e1-9b4f12d268b7', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', 'ea793941-1ca1-4e23-ac0e-784d3a95743a', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('2851a0c1-33ba-42f4-943b-6cba28f2e801', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '9e378453-357b-4395-a342-d53f98d6db46', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('be0e1d5d-6aaf-42f6-b79e-977a0462fd8a', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '37191c9a-19b7-43aa-9ad5-369100f1407c', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('20003675-980e-47d0-9029-0b554e1d7f2e', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '61da313d-4b5f-40b4-9bc3-55b57ebf18d1', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('6c71b945-0dee-47c3-b891-6b0320d423b2', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '3064dd2b-38d6-46ba-965e-21a101da688c', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Permission" VALUES ('1c636280-a2b5-428d-9c61-528d3cc5e39b', '697da404-a1e6-4e8d-996d-7f488cedc250', '8f16a2cd-b613-4419-bfa5-996f16beaa6a', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('f6ac7053-8b27-429d-9935-8b79e69e3447', '697da404-a1e6-4e8d-996d-7f488cedc250', '4fc642f4-18bb-4b18-980b-7e41e804720c', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('6ce1f77d-6358-4aa0-b432-5c6eb757cb8c', '697da404-a1e6-4e8d-996d-7f488cedc250', '4d238c00-d8c0-4ed2-a803-41caf772820e', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('21fdd8d9-9e5d-4df2-811e-8c8283dbfb94', '697da404-a1e6-4e8d-996d-7f488cedc250', 'fd9ac9a5-be38-426c-b38a-8bda75420ffc', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('47ff4ce1-e525-4d04-aadf-4e4ff285e424', '697da404-a1e6-4e8d-996d-7f488cedc250', '48d6f0b5-5b11-422c-bee9-d1caa8447966', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('2f60796e-8fbb-4488-b383-24740a5a681d', '697da404-a1e6-4e8d-996d-7f488cedc250', 'e1b37b30-e000-4c24-8976-8c9fa78042b0', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('60f5ab0f-f5f4-422a-ac71-5863f518d4d4', '697da404-a1e6-4e8d-996d-7f488cedc250', '0c437ad9-c18e-46df-b2c1-c1330601ac3c', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('770bb614-dfbc-4406-9c46-ad3f0e1923d8', '697da404-a1e6-4e8d-996d-7f488cedc250', '9ff718db-c9f9-4fd4-8cc2-d6212b74c336', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('4b86bf4a-16cc-419f-8e52-d2e4250b36af', '697da404-a1e6-4e8d-996d-7f488cedc250', '6b52bc0a-f2b6-4422-8ef8-dde0c5b81f96', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('e3637c24-48bc-408c-9ed0-d5885e208d9b', '697da404-a1e6-4e8d-996d-7f488cedc250', '52ff7472-67da-4f9b-ba90-ec5468492f32', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('1074ec66-87f2-4210-bc1f-7baadebf724b', '697da404-a1e6-4e8d-996d-7f488cedc250', '45d1f4ea-a1e5-4e48-b6a7-141e1fa63b67', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('c87ca149-470a-42cd-9ba5-677a31d42378', '697da404-a1e6-4e8d-996d-7f488cedc250', 'e38ca869-3931-427b-9f19-724416354d24', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('f7c4e12f-b8f1-4ad1-9c8e-316037332b41', '697da404-a1e6-4e8d-996d-7f488cedc250', '63183e8c-0c27-4642-b783-53290cc7e957', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('2d636fe1-db7c-40db-a4a9-37e664094a7d', '697da404-a1e6-4e8d-996d-7f488cedc250', 'df07b7c5-a08e-4404-809f-0e4315859c9e', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('6fe43fa9-857e-4c35-a7b1-c403b22b7c19', '697da404-a1e6-4e8d-996d-7f488cedc250', '6df447b0-d2c2-47a2-afd0-db418db85e76', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('31203c86-90cb-48ed-98d4-398264d5013b', '697da404-a1e6-4e8d-996d-7f488cedc250', '86714c51-fce0-498d-9b4f-32fd00ea26a0', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('dfabe316-8aa3-4ff7-8b5b-58a26fc23a00', '697da404-a1e6-4e8d-996d-7f488cedc250', '18cf7039-a676-4510-8364-033fa086fdfd', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('a1f2daea-93b1-41ca-be06-3c5adab0f992', '697da404-a1e6-4e8d-996d-7f488cedc250', 'd62fde7d-061a-4134-a1a5-88d084299852', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('930d6388-6d5a-48aa-a2eb-8083c759b56b', '697da404-a1e6-4e8d-996d-7f488cedc250', '3bceaa2a-4444-4593-8cf1-acf55ee208bf', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('7950c9b2-4a34-4b0e-b010-fe7d6fa40c9c', '697da404-a1e6-4e8d-996d-7f488cedc250', 'ca0a8df9-7daa-4abf-b9dc-9e3f15bed7c4', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('c168fb2a-5b2e-4c82-b292-0f0f3d512ee2', '697da404-a1e6-4e8d-996d-7f488cedc250', 'e648628c-e4f3-4abe-a3d6-452b10dd308f', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('72481323-59a9-4bfa-a146-a3fa97d996a9', '697da404-a1e6-4e8d-996d-7f488cedc250', '3024936c-5e4f-4b0a-a5a8-6360d8294987', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('daa25b82-f3c5-4e60-91c4-be6c87905b73', '697da404-a1e6-4e8d-996d-7f488cedc250', '881a0e88-22e8-49ea-813c-4eaa4e3d6aaa', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('eb3b4545-faab-4320-b74a-0c10b66eefbf', '697da404-a1e6-4e8d-996d-7f488cedc250', 'f7650658-054e-4dca-8fba-92ffa2421f9d', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('2edfe45d-7105-435f-8f76-13cbbf078cf2', '697da404-a1e6-4e8d-996d-7f488cedc250', 'fa772008-e045-479b-9d7e-09c04b584277', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('0edbb5ac-5b92-4647-9b3a-ede4a101d441', '697da404-a1e6-4e8d-996d-7f488cedc250', 'c6d8811b-1f1d-46dd-9b29-da46b2278a48', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('70be9632-bb9e-4270-92bb-f5b73adf1c72', '697da404-a1e6-4e8d-996d-7f488cedc250', '0f6fcc34-8913-47a7-8b28-0c526a22b947', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('fde57691-4763-4e30-b547-a987f3591db8', '697da404-a1e6-4e8d-996d-7f488cedc250', 'a9a40b3f-a86a-4d47-be45-fda5e5bcfaf8', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('3eb4282d-a029-45b8-a9cf-dfb12c25a1e3', '697da404-a1e6-4e8d-996d-7f488cedc250', '891b01b1-bd1b-4caf-93b2-f7dadd7d2b4b', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('39f25fbf-71b7-4355-a91b-a217fc7c7fbf', '697da404-a1e6-4e8d-996d-7f488cedc250', '8d3e24e9-fcac-42a8-b1b8-d26d71d06985', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('4881dd80-0831-4e90-877b-44db3563b058', '697da404-a1e6-4e8d-996d-7f488cedc250', '2a784982-3f4e-4fea-a44e-ab9f7aa302f3', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('63f5f5ac-35c8-4231-bec6-48b7b458b0e4', '697da404-a1e6-4e8d-996d-7f488cedc250', '240ed870-775b-42d4-abb3-5d915df5c57f', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('efd9e7b7-57bd-44cb-977f-5be98af32f59', '697da404-a1e6-4e8d-996d-7f488cedc250', '7e88d5a1-0517-49ac-b476-f8da0dfa1ef7', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('6bc41f5b-b18e-44ee-b3e2-28521e3de101', '697da404-a1e6-4e8d-996d-7f488cedc250', '74ca9688-7700-4322-b36f-e1180c5b996b', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('9410a00c-2149-403c-944a-9cafc465083b', '697da404-a1e6-4e8d-996d-7f488cedc250', 'dea4e038-592f-4532-ac86-c7de25a3416c', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('7eb48a24-7b79-4f3d-8bf6-42aa8028967b', '697da404-a1e6-4e8d-996d-7f488cedc250', '5dc9be35-dfad-493e-99c4-fdca4ddff1f5', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('032d673c-e4ff-4b59-8d2a-130fc55f8afa', '697da404-a1e6-4e8d-996d-7f488cedc250', '1ee566d9-d5ef-456a-8009-d67bb026b4b0', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('9991d8f8-9125-470b-a7f1-316aea27e298', '697da404-a1e6-4e8d-996d-7f488cedc250', '28a745e9-ff3a-49c2-bebc-e269146652e6', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('74051cb8-4cf5-42a5-9370-f3ef758451d4', '697da404-a1e6-4e8d-996d-7f488cedc250', '2e7aa93e-978c-42e3-aef3-49ec2c7fa183', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('3881f6ca-7851-49c1-a968-8fec04bc7e8a', '697da404-a1e6-4e8d-996d-7f488cedc250', 'aaf9caab-e4cc-491c-bf9c-d5fe81b9d867', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('b96005cd-8c49-4a40-9190-a929c97a4aaa', '697da404-a1e6-4e8d-996d-7f488cedc250', '596eba6b-6b80-495a-bf9d-f90fdfb9e49d', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('625f4064-dc25-4fc4-aea3-c134ba20c949', '697da404-a1e6-4e8d-996d-7f488cedc250', '03404a66-50aa-4b21-8c93-9dcddaeffdb7', '2024-09-26 12:11:17.733');
+INSERT INTO "public"."Permission" VALUES ('7939f8bc-9b6a-4783-a260-82e5b0725a10', '697da404-a1e6-4e8d-996d-7f488cedc250', '572c5097-d28f-48b4-899d-3aaf46b8d668', '2024-09-26 12:11:17.733');

+ 71 - 0
postgreSQL/Post.sql

@@ -0,0 +1,71 @@
+/*
+ Navicat Premium Dump SQL
+
+ Source Server         : postgreSQL
+ Source Server Type    : PostgreSQL
+ Source Server Version : 160003 (160003)
+ Source Host           : localhost:5432
+ Source Catalog        : vue3-admin
+ Source Schema         : public
+
+ Target Server Type    : PostgreSQL
+ Target Server Version : 160003 (160003)
+ File Encoding         : 65001
+
+ Date: 31/10/2024 10:17:22
+*/
+
+
+-- ----------------------------
+-- Table structure for Post
+-- ----------------------------
+DROP TABLE IF EXISTS "public"."Post";
+CREATE TABLE "public"."Post" (
+  "id" text COLLATE "pg_catalog"."default" NOT NULL,
+  "name" text COLLATE "pg_catalog"."default" NOT NULL,
+  "orgId" text COLLATE "pg_catalog"."default" NOT NULL,
+  "parentId" text COLLATE "pg_catalog"."default",
+  "sort" int4 NOT NULL,
+  "description" text COLLATE "pg_catalog"."default",
+  "createdAt" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  "updatedAt" timestamp(3) NOT NULL
+)
+;
+
+-- ----------------------------
+-- Records of Post
+-- ----------------------------
+INSERT INTO "public"."Post" VALUES ('1d83e15c-3dba-4cbf-bd23-e1f37b3ab834', '程序员', 'f45cd48b-e703-49db-91be-ae7f594e73e0', NULL, 1, '程序员(英文Programmer)是从事程序开发、程序维护的基层工作人员。一般将程序员分为程序设计人员和程序编码人员,但两者的界限并不非常清楚。随着互联网的不断普及,网络上把男程序员称作“程序猿”。或将男女程序员统称为“工程师(攻城狮)”。', '2024-07-17 00:39:54.384', '2024-07-17 01:36:06.188');
+INSERT INTO "public"."Post" VALUES ('9af54e7f-b31d-4306-8fb3-ada93326f63b', 'UI 设计师', '0da77343-0747-42fe-beff-25ee98bc7a88', NULL, 1, '', '2024-07-17 07:27:22.185', '2024-07-17 07:27:22.185');
+INSERT INTO "public"."Post" VALUES ('e632b172-3138-44ef-b246-912ff18d6a29', '初级设计师', 'b924df00-77ed-49b7-a8b4-181f0b259c18', '9af54e7f-b31d-4306-8fb3-ada93326f63b', 1, '', '2024-07-17 07:27:50.533', '2024-07-17 07:27:50.533');
+INSERT INTO "public"."Post" VALUES ('f401a468-5a9f-4430-85a2-d31177df034a', '中级设计师', 'b924df00-77ed-49b7-a8b4-181f0b259c18', '9af54e7f-b31d-4306-8fb3-ada93326f63b', 1, '', '2024-07-17 07:28:13.934', '2024-07-17 07:28:13.934');
+INSERT INTO "public"."Post" VALUES ('86d77183-6574-4e0b-91ae-1619c856d31a', '高级设计师', 'b924df00-77ed-49b7-a8b4-181f0b259c18', '9af54e7f-b31d-4306-8fb3-ada93326f63b', 1, '', '2024-07-17 07:28:33.81', '2024-07-17 07:28:33.81');
+INSERT INTO "public"."Post" VALUES ('34f2d5e1-7378-46b3-8f0c-56cfdbb8f3eb', '前端工程师', '9382c3d0-42ef-496b-961f-f0bcee6edfbf', '1d83e15c-3dba-4cbf-bd23-e1f37b3ab834', 1, '前端工程师是互联网时代软件产品研发中不可缺少的一种专业研发角色。从狭义上讲,前端工程师使用 HTML、CSS、JavaScript 等专业技能和工具将产品UI设计稿实现成网站产品,涵盖用户PC端、移动端网页,处理视觉和交互问题。从广义上来讲,所有用户终端产品与视觉和交互有关的部分,都是前端工程师的专业领域。', '2024-07-17 01:02:27.831', '2024-07-17 01:02:27.831');
+INSERT INTO "public"."Post" VALUES ('f6c90653-8110-4585-aead-20d526dc33f7', 'Java工程师', '9382c3d0-42ef-496b-961f-f0bcee6edfbf', '1d83e15c-3dba-4cbf-bd23-e1f37b3ab834', 1, '负责项目相关开发工作,包括参与系统需求分析、研发设计', '2024-07-17 01:55:04.562', '2024-07-17 01:55:04.562');
+INSERT INTO "public"."Post" VALUES ('155b3d9d-40d3-4db3-9c40-1ef2aac15547', '市场运营', '2eaab2c3-4872-49af-b647-78ba9c120df8', NULL, 1, '写文案;活动策划或活动执行;用户分析;市场合作;数据分析;地推;充当客服;部门对接', '2024-09-02 09:51:15.557', '2024-09-02 09:51:15.557');
+INSERT INTO "public"."Post" VALUES ('edbe1b2b-dc29-4ca1-a6ad-4f6707f2d2be', '高级运营', '8233a4de-02f8-49d8-85e8-5a92fd8552e0', '155b3d9d-40d3-4db3-9c40-1ef2aac15547', 1, '', '2024-09-02 09:51:28.671', '2024-09-02 09:51:28.671');
+INSERT INTO "public"."Post" VALUES ('49ad32a8-e431-4967-8a44-82413f892f5e', '中级运营', '038d606e-304d-4cff-bb09-70f5be4a8f19', '155b3d9d-40d3-4db3-9c40-1ef2aac15547', 1, '', '2024-09-02 09:51:52.612', '2024-09-02 09:51:52.612');
+INSERT INTO "public"."Post" VALUES ('1ea27ba8-aac7-43ea-9934-a5a53429c204', '实习生', 'f45cd48b-e703-49db-91be-ae7f594e73e0', '155b3d9d-40d3-4db3-9c40-1ef2aac15547', 1, '', '2024-09-02 09:52:03.333', '2024-09-02 09:52:03.333');
+INSERT INTO "public"."Post" VALUES ('e9441c59-336b-43db-9465-9c0ecaec1d76', 'C++ 开发', '7657fca9-acb5-42a9-ab6a-782d34ab9b62', '1d83e15c-3dba-4cbf-bd23-e1f37b3ab834', 1, '', '2024-09-02 09:52:21.722', '2024-09-02 09:52:21.722');
+INSERT INTO "public"."Post" VALUES ('f5cc1862-30f2-4ae7-9e9a-f158c6a89275', '董事会', 'f45cd48b-e703-49db-91be-ae7f594e73e0', NULL, 1, '', '2024-09-04 03:02:13.986', '2024-09-04 03:02:13.986');
+INSERT INTO "public"."Post" VALUES ('825e7fd6-74db-495d-9ab9-9fa18c4c0bf3', '主席', 'f45cd48b-e703-49db-91be-ae7f594e73e0', 'f5cc1862-30f2-4ae7-9e9a-f158c6a89275', 1, '', '2024-09-04 03:02:31.948', '2024-09-04 03:02:31.948');
+INSERT INTO "public"."Post" VALUES ('42fa3681-de70-4d5f-95b8-db5a66101ecc', 'CEO', '460e32b7-6c69-47b2-ab01-30268952f52e', 'f5cc1862-30f2-4ae7-9e9a-f158c6a89275', 1, '', '2024-09-04 03:02:53.456', '2024-09-04 03:02:53.456');
+INSERT INTO "public"."Post" VALUES ('868c4fcf-42b0-4c59-bb98-e97d6de6f521', 'CFO', '38c80d63-c18e-4dc4-9b36-f962146af156', 'f5cc1862-30f2-4ae7-9e9a-f158c6a89275', 1, '', '2024-09-04 03:03:18.153', '2024-09-04 03:03:18.153');
+
+-- ----------------------------
+-- Indexes structure for table Post
+-- ----------------------------
+CREATE UNIQUE INDEX "Post_name_key" ON "public"."Post" USING btree (
+  "name" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
+);
+
+-- ----------------------------
+-- Primary Key structure for table Post
+-- ----------------------------
+ALTER TABLE "public"."Post" ADD CONSTRAINT "Post_pkey" PRIMARY KEY ("id");
+
+-- ----------------------------
+-- Foreign Keys structure for table Post
+-- ----------------------------
+ALTER TABLE "public"."Post" ADD CONSTRAINT "Post_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "public"."Organization" ("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+ALTER TABLE "public"."Post" ADD CONSTRAINT "Post_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "public"."Post" ("id") ON DELETE SET NULL ON UPDATE CASCADE;

+ 55 - 0
postgreSQL/Role.sql

@@ -0,0 +1,55 @@
+/*
+ Navicat Premium Dump SQL
+
+ Source Server         : postgreSQL
+ Source Server Type    : PostgreSQL
+ Source Server Version : 160003 (160003)
+ Source Host           : localhost:5432
+ Source Catalog        : vue3-admin
+ Source Schema         : public
+
+ Target Server Type    : PostgreSQL
+ Target Server Version : 160003 (160003)
+ File Encoding         : 65001
+
+ Date: 31/10/2024 10:17:26
+*/
+
+
+-- ----------------------------
+-- Table structure for Role
+-- ----------------------------
+DROP TABLE IF EXISTS "public"."Role";
+CREATE TABLE "public"."Role" (
+  "id" text COLLATE "pg_catalog"."default" NOT NULL,
+  "name" text COLLATE "pg_catalog"."default" NOT NULL,
+  "code" text COLLATE "pg_catalog"."default" NOT NULL,
+  "description" text COLLATE "pg_catalog"."default",
+  "sort" int4 NOT NULL,
+  "createdAt" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  "updatedAt" timestamp(3) NOT NULL
+)
+;
+
+-- ----------------------------
+-- Records of Role
+-- ----------------------------
+INSERT INTO "public"."Role" VALUES ('2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '系统管理员', 'System Admin', '只拥有系统管理权限', 1, '2024-08-23 02:17:36.278', '2024-09-02 09:47:35.549');
+INSERT INTO "public"."Role" VALUES ('e02b5eec-d7b9-4ff8-862c-0151448a390c', '行政管理员', 'Administrative Admin', '只拥有智能行政模块权限', 1, '2024-09-02 09:49:18.444', '2024-09-19 03:17:50.487');
+INSERT INTO "public"."Role" VALUES ('6db049fe-c944-4680-b6dc-f9f40d6ad018', '超级管理员', 'Super Admin', '拥有系统全部权限', 88, '2024-08-22 07:03:04.323', '2024-09-26 12:10:48.002');
+INSERT INTO "public"."Role" VALUES ('697da404-a1e6-4e8d-996d-7f488cedc250', '查看管理员', 'View Admin', '仅支持菜单查看,不支持新增、编辑、删除等操作!', 1, '2024-08-23 05:55:44.978', '2024-09-26 12:11:17.733');
+
+-- ----------------------------
+-- Indexes structure for table Role
+-- ----------------------------
+CREATE UNIQUE INDEX "Role_code_key" ON "public"."Role" USING btree (
+  "code" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
+);
+CREATE UNIQUE INDEX "Role_name_key" ON "public"."Role" USING btree (
+  "name" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
+);
+
+-- ----------------------------
+-- Primary Key structure for table Role
+-- ----------------------------
+ALTER TABLE "public"."Role" ADD CONSTRAINT "Role_pkey" PRIMARY KEY ("id");

+ 84 - 0
postgreSQL/User.sql

@@ -0,0 +1,84 @@
+/*
+ Navicat Premium Dump SQL
+
+ Source Server         : postgreSQL
+ Source Server Type    : PostgreSQL
+ Source Server Version : 160003 (160003)
+ Source Host           : localhost:5432
+ Source Catalog        : vue3-admin
+ Source Schema         : public
+
+ Target Server Type    : PostgreSQL
+ Target Server Version : 160003 (160003)
+ File Encoding         : 65001
+
+ Date: 31/10/2024 10:17:30
+*/
+
+
+-- ----------------------------
+-- Table structure for User
+-- ----------------------------
+DROP TABLE IF EXISTS "public"."User";
+CREATE TABLE "public"."User" (
+  "id" text COLLATE "pg_catalog"."default" NOT NULL,
+  "userName" text COLLATE "pg_catalog"."default" NOT NULL,
+  "password" text COLLATE "pg_catalog"."default" NOT NULL,
+  "cnName" text COLLATE "pg_catalog"."default" NOT NULL,
+  "email" text COLLATE "pg_catalog"."default" NOT NULL,
+  "phone" text COLLATE "pg_catalog"."default" NOT NULL,
+  "avatar" text COLLATE "pg_catalog"."default" NOT NULL,
+  "sex" "public"."Sex" NOT NULL DEFAULT 'FEMALE'::"Sex",
+  "status" "public"."Status" NOT NULL DEFAULT 'ACTIVE'::"Status",
+  "sort" int4 NOT NULL,
+  "token" text COLLATE "pg_catalog"."default",
+  "tags" text[] COLLATE "pg_catalog"."default" DEFAULT ARRAY[]::text[],
+  "city" text[] COLLATE "pg_catalog"."default" DEFAULT ARRAY[]::text[],
+  "address" text COLLATE "pg_catalog"."default",
+  "roleId" text COLLATE "pg_catalog"."default" NOT NULL,
+  "orgId" text COLLATE "pg_catalog"."default" NOT NULL,
+  "postId" text COLLATE "pg_catalog"."default" NOT NULL,
+  "loginCount" int4 NOT NULL DEFAULT 0,
+  "lastIp" text COLLATE "pg_catalog"."default",
+  "lastLoginAt" timestamp(3),
+  "createdAt" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  "updatedAt" timestamp(3) NOT NULL
+)
+;
+
+-- ----------------------------
+-- Records of User
+-- ----------------------------
+INSERT INTO "public"."User" VALUES ('b62c0c5a-ac9f-4d7d-863c-fbfa148bbc4c', 'liuyifei', '$2b$10$o1dlWm4dU8O9QxkYZ0ExfOckX9Ba9.plwRRIgkxIg.Lr3gQXwHeGa', '刘亦菲', 'me@liuyifei.com', '13888888888', 'http://localhost:3000/static/image/2024-08/f92269b2-77b7-48ef-83b9-e8bd4970c304.jpeg', 'FEMALE', 'ACTIVE', 1, NULL, '{女神,灵儿}', '{11,1101,110105}', '高档别墅', '697da404-a1e6-4e8d-996d-7f488cedc250', 'e5f4ae69-633b-48ff-8ef1-b92597f2a26c', '86d77183-6574-4e0b-91ae-1619c856d31a', 3, '::1', '2024-09-04 06:49:56.131', '2024-08-27 05:42:41.646', '2024-09-04 06:50:04.222');
+INSERT INTO "public"."User" VALUES ('c698c8e8-3aa0-4dec-b1cd-7d37660d1519', 'wangsicong', '$2b$10$z2MAN9zPt5c6MrcCBh1GDuhKnRdBKjPFUtJOShxdNHBOXJmZBL3ca', '王思聪', 'wcs@wangda.com', '18888888881', 'http://localhost:3000/static/image/2024-09/2126ab07-c104-4fe3-a6c2-1c1d72223614.jpeg', 'MALE', 'ACTIVE', 1, NULL, '{富二代}', '{21,2102,210202}', '啊实打实的', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '40129577-049f-4f40-9e2e-2c1188e4695f', '1ea27ba8-aac7-43ea-9934-a5a53429c204', 3, '::1', '2024-09-04 06:24:05.714', '2024-09-04 03:31:05.622', '2024-09-04 06:25:45.499');
+INSERT INTO "public"."User" VALUES ('ba54e74c-86cb-4bfa-a0bc-71813175de9e', 'mahuateng', '$2b$10$OyO/XuTr4mZt6KIHLPvnS.A62G7Swphk7l2o//H0rnPjqbvgKHbqq', '马化腾', 'pony@tencent.com', '18888888880', 'http://localhost:3000/static/image/2024-09/a370df3c-4d3d-4e2d-81ac-25790e2a1789.jpeg', 'MALE', 'ACTIVE', 1, 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyTmFtZSI6Im1haHVhdGVuZyIsInN1YiI6ImJhNTRlNzRjLTg2Y2ItNGJmYS1hMGJjLTcxODEzMTc1ZGU5ZSIsImlhdCI6MTcyNTQzMTIyOCwiZXhwIjoxNzI1NjkwNDI4fQ._okWes1SjxnUZJCsLxRwc9HjURyxqDRYCn-yJqhZaOE', '{腾讯掌门人}', '{44,4403,440305}', '粤海街道', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '32cab8f0-13df-4876-83c5-86089390dbb7', '42fa3681-de70-4d5f-95b8-db5a66101ecc', 1, '::1', '2024-09-04 06:27:08.208', '2024-09-04 03:28:58.81', '2024-09-04 06:27:08.21');
+INSERT INTO "public"."User" VALUES ('ea35984a-34f6-4da3-9f50-314f4b719ea6', 'mayun', '$2b$10$uhBo0HEIikMH9dFSfuCGj.fHYCDz/e55tgR/7ALLCEL2w/uJTh7Py', '马云', 'mayun@alibaba.com', '18888888888', 'http://localhost:3000/static/image/2024-09/ac7b73c5-3c4e-41c4-94a8-21393e5682e4.jpeg', 'MALE', 'ACTIVE', 1, NULL, '{首富,男神}', '{33,3301,330110}', '阿里巴巴大厦', '6db049fe-c944-4680-b6dc-f9f40d6ad018', 'f45cd48b-e703-49db-91be-ae7f594e73e0', '825e7fd6-74db-495d-9ab9-9fa18c4c0bf3', 2, '::1', '2024-09-04 06:16:30.121', '2024-09-04 03:01:21.011', '2024-09-04 06:16:38.93');
+INSERT INTO "public"."User" VALUES ('b485e3c1-0790-4007-adef-849537c291f5', 'leijun', '$2b$10$7Ywy/tKMzLmiWUEuXD4wG.Otq9VycEJcPtcGOEcKlt28jbo2k4.pO', '雷军', 'leijun@xiaomi.com', '18888888883', 'http://localhost:3000/static/image/2024-09/fcdab14e-29d4-43e3-8630-9cf064646f35.jpeg', 'MALE', 'ACTIVE', 1, 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyTmFtZSI6ImxlaWp1biIsInN1YiI6ImI0ODVlM2MxLTA3OTAtNDAwNy1hZGVmLTg0OTUzN2MyOTFmNSIsImlhdCI6MTcyNTk1OTE0MiwiZXhwIjoxNzI2MjE4MzQyfQ.r8wqW1bGycJ2FrNdu8rdbOmsw6PWPkBkdexvpzPkH7w', '{"Are You OK",小米SU7}', '{11,1101,110105}', '小米总部', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '68c4ac85-3f4a-4ca0-9112-562e91a1d6a2', '42fa3681-de70-4d5f-95b8-db5a66101ecc', 5, '::1', '2024-09-10 09:05:42.137', '2024-09-04 05:44:44.16', '2024-09-10 09:05:42.138');
+INSERT INTO "public"."User" VALUES ('1785737b-8daf-4bc1-ae49-8769c256c209', 'lizhien', '$2b$10$HZUnnFSlz5E3N.DkLBQWu.AeyAOTvAayS6C.6osxcCTjYSm6zPt.6', '李知恩', 'lizhien@me.com', '13800138000', 'http://localhost:3000/static/image/2024-07/6f6e22a3-1e6a-4aa3-bbe9-6b2b0e6ea5aa.jpeg', 'FEMALE', 'INACTIVE', 1, NULL, '{美女}', '{11,1101,110101}', '首尔区', '2564f9b6-9288-49d4-b1b2-2d6f4f7946f3', '2eaab2c3-4872-49af-b647-78ba9c120df8', 'f401a468-5a9f-4430-85a2-d31177df034a', 2, '::1', '2024-08-23 03:36:37.955', '2024-07-30 06:38:44.512', '2024-08-23 03:36:54.871');
+INSERT INTO "public"."User" VALUES ('bf9c32dc-2363-4a31-9e7f-74544f7d04a4', 'zhangruonan', '$2b$10$LH1qhhLPxCIXMETxYqHDtek05qUAtMP9fQvZf6xJ23dPtG5JHx50G', '章若楠', 'zyn@yule.com', '18888888884', 'http://localhost:3000/static/image/2024-09/72840555-ee20-4679-a54d-4b39c622567d.jpeg', 'FEMALE', 'ACTIVE', 1, 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyTmFtZSI6InpoYW5ncnVvbmFuIiwic3ViIjoiYmY5YzMyZGMtMjM2My00YTMxLTllN2YtNzQ1NDRmN2QwNGE0IiwiaWF0IjoxNzI1OTU4MTQwLCJleHAiOjE3MjYyMTczNDB9.v2COO1RKNHMkNAyJ-nH5OyoooIN8JCcvXXmBeSN5kbI', '{女神}', '{13,1303,130303}', '别墅967号', 'e02b5eec-d7b9-4ff8-862c-0151448a390c', 'b924df00-77ed-49b7-a8b4-181f0b259c18', 'f401a468-5a9f-4430-85a2-d31177df034a', 9, '::1', '2024-09-10 08:49:00.671', '2024-09-04 05:46:47.509', '2024-09-10 08:49:00.674');
+INSERT INTO "public"."User" VALUES ('dddd7ba9-c1d4-4a6b-b946-f05e2f79880f', 'Admin', '$2b$10$lfMvyYSrWNjVF55UhxeC0uoVYgf7GwWBhXu1BZAlvHXoGf./E7Lk2', '谢明伟', 'baiwumm@foxmail.com', '15920157932', 'http://localhost:3000/static/image/2024-07/cc9e77ee-cf84-48e8-a9d0-dc3e9d21224c.jpeg', 'MALE', 'ACTIVE', 88, 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyTmFtZSI6IkFkbWluIiwic3ViIjoiZGRkZDdiYTktYzFkNC00YTZiLWI5NDYtZjA1ZTJmNzk4ODBmIiwiaWF0IjoxNzMwMzQwNzQ0LCJleHAiOjE3MzA1OTk5NDR9.T9cdDxVEBGYKs25z68DQZ5cUGTWoKuqkII9Dpau0-k8', '{热血青年,佛系,追求自由,做自己喜欢做的事}', '{44,4403,440305}', '粤海街道', '6db049fe-c944-4680-b6dc-f9f40d6ad018', '32cab8f0-13df-4876-83c5-86089390dbb7', '34f2d5e1-7378-46b3-8f0c-56cfdbb8f3eb', 216, '::1', '2024-10-31 02:12:24.833', '2024-07-30 02:35:25.835', '2024-10-31 02:12:24.835');
+
+-- ----------------------------
+-- Indexes structure for table User
+-- ----------------------------
+CREATE UNIQUE INDEX "User_email_key" ON "public"."User" USING btree (
+  "email" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
+);
+CREATE UNIQUE INDEX "User_phone_key" ON "public"."User" USING btree (
+  "phone" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
+);
+CREATE UNIQUE INDEX "User_userName_key" ON "public"."User" USING btree (
+  "userName" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
+);
+
+-- ----------------------------
+-- Primary Key structure for table User
+-- ----------------------------
+ALTER TABLE "public"."User" ADD CONSTRAINT "User_pkey" PRIMARY KEY ("id");
+
+-- ----------------------------
+-- Foreign Keys structure for table User
+-- ----------------------------
+ALTER TABLE "public"."User" ADD CONSTRAINT "User_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "public"."Organization" ("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+ALTER TABLE "public"."User" ADD CONSTRAINT "User_postId_fkey" FOREIGN KEY ("postId") REFERENCES "public"."Post" ("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+ALTER TABLE "public"."User" ADD CONSTRAINT "User_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "public"."Role" ("id") ON DELETE RESTRICT ON UPDATE CASCADE;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 655 - 0
postgreSQL/public.sql


+ 24 - 0
server/.eslintrc.js

@@ -0,0 +1,24 @@
+module.exports = {
+  parser: '@typescript-eslint/parser',
+  parserOptions: {
+    project: 'tsconfig.json',
+    tsconfigRootDir: __dirname,
+    sourceType: 'module',
+  },
+  plugins: ['@typescript-eslint/eslint-plugin', 'simple-import-sort'],
+  extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
+  root: true,
+  env: {
+    node: true,
+    jest: true,
+  },
+  ignorePatterns: ['.eslintrc.js'],
+  rules: {
+    '@typescript-eslint/interface-name-prefix': 'off',
+    '@typescript-eslint/explicit-function-return-type': 'off',
+    '@typescript-eslint/explicit-module-boundary-types': 'off',
+    '@typescript-eslint/no-explicit-any': 'off',
+    'simple-import-sort/imports': 'error',
+    'simple-import-sort/exports': 'error',
+  },
+};

+ 57 - 0
server/.gitignore

@@ -0,0 +1,57 @@
+# compiled output
+/dist
+/node_modules
+/build
+/upload
+
+# Logs
+logs
+*.log
+npm-debug.log*
+pnpm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+
+# OS
+.DS_Store
+
+# Tests
+/coverage
+/.nyc_output
+
+# IDEs and editors
+/.idea
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+
+# dotenv environment variable files
+.env
+# .env.development.local
+# .env.test.local
+# .env.production.local
+.env.local
+
+# temp directory
+.temp
+.tmp
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

+ 10 - 0
server/.prettierrc

@@ -0,0 +1,10 @@
+{
+  "endOfLine": "auto",
+  "printWidth": 120,
+  "semi": true,
+  "singleQuote": true,
+  "tabWidth": 2,
+  "trailingComma": "all",
+  "bracketSpacing": true
+}
+

+ 73 - 0
server/README.md

@@ -0,0 +1,73 @@
+<p align="center">
+  <a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="200" alt="Nest Logo" /></a>
+</p>
+
+[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
+[circleci-url]: https://circleci.com/gh/nestjs/nest
+
+  <p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
+    <p align="center">
+<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
+<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
+<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
+<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
+<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
+<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
+<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
+<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
+  <a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
+    <a href="https://opencollective.com/nest#sponsor"  target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
+  <a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
+</p>
+  <!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
+  [![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->
+
+## Description
+
+[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
+
+## Installation
+
+```bash
+$ pnpm install
+```
+
+## Running the app
+
+```bash
+# development
+$ pnpm run start
+
+# watch mode
+$ pnpm run start:dev
+
+# production mode
+$ pnpm run start:prod
+```
+
+## Test
+
+```bash
+# unit tests
+$ pnpm run test
+
+# e2e tests
+$ pnpm run test:e2e
+
+# test coverage
+$ pnpm run test:cov
+```
+
+## Support
+
+Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
+
+## Stay in touch
+
+- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
+- Website - [https://nestjs.com](https://nestjs.com/)
+- Twitter - [@nestframework](https://twitter.com/nestframework)
+
+## License
+
+Nest is [MIT licensed](LICENSE).

+ 8 - 0
server/nest-cli.json

@@ -0,0 +1,8 @@
+{
+  "$schema": "https://json.schemastore.org/nest-cli",
+  "collection": "@nestjs/schematics",
+  "sourceRoot": "src",
+  "compilerOptions": {
+    "deleteOutDir": true
+  }
+}

+ 104 - 0
server/package.json

@@ -0,0 +1,104 @@
+{
+  "name": "vue3-admin",
+  "version": "0.0.1",
+  "description": "",
+  "author": {
+    "name": "baiwumm",
+    "email": "baiwumm@foxmail.com",
+    "url": "https://baiwumm.com"
+  },
+  "private": true,
+  "license": "UNLICENSED",
+  "scripts": {
+    "build": "nest build",
+    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
+    "start": "nest start",
+    "start:dev": "nest build --webpack --webpackPath webpack-hmr.config.js --watch",
+    "start:debug": "nest start --debug --watch",
+    "start:prod": "node dist/main",
+    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
+    "test": "jest",
+    "test:watch": "jest --watch",
+    "test:cov": "jest --coverage",
+    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
+    "test:e2e": "jest --config ./test/jest-e2e.json"
+  },
+  "dependencies": {
+    "@nestjs/axios": "^3.0.3",
+    "@nestjs/common": "^10.0.0",
+    "@nestjs/core": "^10.0.0",
+    "@nestjs/event-emitter": "^2.0.4",
+    "@nestjs/jwt": "^10.2.0",
+    "@nestjs/mapped-types": "*",
+    "@nestjs/passport": "^10.0.3",
+    "@nestjs/platform-express": "^10.3.10",
+    "@prisma/client": "5.16.1",
+    "bcryptjs": "^3.0.2",
+    "chalk": "^4.1.2",
+    "class-transformer": "^0.5.1",
+    "class-validator": "^0.14.1",
+    "dayjs": "^1.11.11",
+    "express": "^4.19.2",
+    "express-session": "^1.18.0",
+    "multer": "1.4.5-lts.1",
+    "nest-winston": "^1.9.7",
+    "passport-jwt": "^4.0.1",
+    "reflect-metadata": "^0.2.0",
+    "rxjs": "^7.8.1",
+    "svg-captcha": "^1.4.0",
+    "ua-parser-js": "^1.0.38",
+    "uuid": "^10.0.0",
+    "winston": "^3.14.2",
+    "winston-daily-rotate-file": "^5.0.0",
+    "xlsx": "^0.18.5"
+  },
+  "devDependencies": {
+    "@nestjs/cli": "^10.0.0",
+    "@nestjs/schematics": "^10.0.0",
+    "@nestjs/swagger": "^7.4.0",
+    "@nestjs/testing": "^10.0.0",
+    "@types/express": "^4.17.17",
+    "@types/express-session": "^1.18.0",
+    "@types/jest": "^29.5.2",
+    "@types/multer": "^1.4.11",
+    "@types/node": "^20.3.1",
+    "@types/supertest": "^6.0.0",
+    "@typescript-eslint/eslint-plugin": "^7.0.0",
+    "@typescript-eslint/parser": "^7.0.0",
+    "eslint": "^8.42.0",
+    "eslint-config-prettier": "^9.0.0",
+    "eslint-plugin-prettier": "^5.0.0",
+    "eslint-plugin-simple-import-sort": "^12.1.1",
+    "jest": "^29.5.0",
+    "prettier": "^3.0.0",
+    "prisma": "^5.16.1",
+    "run-script-webpack-plugin": "^0.2.0",
+    "source-map-support": "^0.5.21",
+    "supertest": "^7.0.0",
+    "swagger-ui-express": "^5.0.1",
+    "ts-jest": "^29.1.0",
+    "ts-loader": "^9.4.3",
+    "ts-node": "^10.9.1",
+    "tsconfig-paths": "^4.2.0",
+    "typescript": "^5.1.3",
+    "webpack": "^5.94.0",
+    "webpack-node-externals": "^3.0.0"
+  },
+  "jest": {
+    "moduleFileExtensions": [
+      "js",
+      "json",
+      "ts"
+    ],
+    "rootDir": "src",
+    "testRegex": ".*\\.spec\\.ts$",
+    "transform": {
+      "^.+\\.(t|j)s$": "ts-jest"
+    },
+    "collectCoverageFrom": [
+      "**/*.(t|j)s"
+    ],
+    "coverageDirectory": "../coverage",
+    "testEnvironment": "node"
+  }
+}

+ 6754 - 0
server/pnpm-lock.yaml

@@ -0,0 +1,6754 @@
+lockfileVersion: '9.0'
+
+settings:
+  autoInstallPeers: true
+  excludeLinksFromLockfile: false
+
+importers:
+
+  .:
+    dependencies:
+      '@nestjs/axios':
+        specifier: ^3.0.3
+        version: 3.0.3(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(axios@1.7.4)(rxjs@7.8.1)
+      '@nestjs/common':
+        specifier: ^10.0.0
+        version: 10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nestjs/core':
+        specifier: ^10.0.0
+        version: 10.3.10(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nestjs/event-emitter':
+        specifier: ^2.0.4
+        version: 2.0.4(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10)
+      '@nestjs/jwt':
+        specifier: ^10.2.0
+        version: 10.2.0(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))
+      '@nestjs/mapped-types':
+        specifier: '*'
+        version: 2.0.5(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)
+      '@nestjs/passport':
+        specifier: ^10.0.3
+        version: 10.0.3(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(passport@0.7.0)
+      '@nestjs/platform-express':
+        specifier: ^10.3.10
+        version: 10.3.10(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10)
+      '@prisma/client':
+        specifier: 5.16.1
+        version: 5.16.1(prisma@5.16.1)
+      bcryptjs:
+        specifier: ^3.0.2
+        version: 3.0.2
+      chalk:
+        specifier: ^4.1.2
+        version: 4.1.2
+      class-transformer:
+        specifier: ^0.5.1
+        version: 0.5.1
+      class-validator:
+        specifier: ^0.14.1
+        version: 0.14.1
+      dayjs:
+        specifier: ^1.11.11
+        version: 1.11.11
+      express:
+        specifier: ^4.19.2
+        version: 4.19.2
+      express-session:
+        specifier: ^1.18.0
+        version: 1.18.0
+      multer:
+        specifier: 1.4.5-lts.1
+        version: 1.4.5-lts.1
+      nest-winston:
+        specifier: ^1.9.7
+        version: 1.9.7(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(winston@3.14.2)
+      passport-jwt:
+        specifier: ^4.0.1
+        version: 4.0.1
+      reflect-metadata:
+        specifier: ^0.2.0
+        version: 0.2.2
+      rxjs:
+        specifier: ^7.8.1
+        version: 7.8.1
+      svg-captcha:
+        specifier: ^1.4.0
+        version: 1.4.0
+      ua-parser-js:
+        specifier: ^1.0.38
+        version: 1.0.38
+      uuid:
+        specifier: ^10.0.0
+        version: 10.0.0
+      winston:
+        specifier: ^3.14.2
+        version: 3.14.2
+      winston-daily-rotate-file:
+        specifier: ^5.0.0
+        version: 5.0.0(winston@3.14.2)
+      xlsx:
+        specifier: ^0.18.5
+        version: 0.18.5
+    devDependencies:
+      '@nestjs/cli':
+        specifier: ^10.0.0
+        version: 10.4.2
+      '@nestjs/schematics':
+        specifier: ^10.0.0
+        version: 10.1.2(chokidar@3.6.0)(typescript@5.5.3)
+      '@nestjs/swagger':
+        specifier: ^7.4.0
+        version: 7.4.0(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)
+      '@nestjs/testing':
+        specifier: ^10.0.0
+        version: 10.3.10(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10)(@nestjs/platform-express@10.3.10)
+      '@types/express':
+        specifier: ^4.17.17
+        version: 4.17.21
+      '@types/express-session':
+        specifier: ^1.18.0
+        version: 1.18.0
+      '@types/jest':
+        specifier: ^29.5.2
+        version: 29.5.12
+      '@types/multer':
+        specifier: ^1.4.11
+        version: 1.4.11
+      '@types/node':
+        specifier: ^20.3.1
+        version: 20.14.10
+      '@types/supertest':
+        specifier: ^6.0.0
+        version: 6.0.2
+      '@typescript-eslint/eslint-plugin':
+        specifier: ^7.0.0
+        version: 7.16.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)
+      '@typescript-eslint/parser':
+        specifier: ^7.0.0
+        version: 7.16.0(eslint@8.57.0)(typescript@5.5.3)
+      eslint:
+        specifier: ^8.42.0
+        version: 8.57.0
+      eslint-config-prettier:
+        specifier: ^9.0.0
+        version: 9.1.0(eslint@8.57.0)
+      eslint-plugin-prettier:
+        specifier: ^5.0.0
+        version: 5.1.3(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.2)
+      eslint-plugin-simple-import-sort:
+        specifier: ^12.1.1
+        version: 12.1.1(eslint@8.57.0)
+      jest:
+        specifier: ^29.5.0
+        version: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))
+      prettier:
+        specifier: ^3.0.0
+        version: 3.3.2
+      prisma:
+        specifier: ^5.16.1
+        version: 5.16.1
+      run-script-webpack-plugin:
+        specifier: ^0.2.0
+        version: 0.2.0
+      source-map-support:
+        specifier: ^0.5.21
+        version: 0.5.21
+      supertest:
+        specifier: ^7.0.0
+        version: 7.0.0
+      swagger-ui-express:
+        specifier: ^5.0.1
+        version: 5.0.1(express@4.19.2)
+      ts-jest:
+        specifier: ^29.1.0
+        version: 29.2.0(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@5.5.3)
+      ts-loader:
+        specifier: ^9.4.3
+        version: 9.5.1(typescript@5.5.3)(webpack@5.94.0)
+      ts-node:
+        specifier: ^10.9.1
+        version: 10.9.2(@types/node@20.14.10)(typescript@5.5.3)
+      tsconfig-paths:
+        specifier: ^4.2.0
+        version: 4.2.0
+      typescript:
+        specifier: ^5.1.3
+        version: 5.5.3
+      webpack:
+        specifier: ^5.94.0
+        version: 5.94.0
+      webpack-node-externals:
+        specifier: ^3.0.0
+        version: 3.0.0
+
+packages:
+
+  '@ampproject/remapping@2.3.0':
+    resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
+    engines: {node: '>=6.0.0'}
+
+  '@angular-devkit/core@17.3.8':
+    resolution: {integrity: sha512-Q8q0voCGudbdCgJ7lXdnyaxKHbNQBARH68zPQV72WT8NWy+Gw/tys870i6L58NWbBaCJEUcIj/kb6KoakSRu+Q==}
+    engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
+    peerDependencies:
+      chokidar: ^3.5.2
+    peerDependenciesMeta:
+      chokidar:
+        optional: true
+
+  '@angular-devkit/schematics-cli@17.3.8':
+    resolution: {integrity: sha512-TjmiwWJarX7oqvNiRAroQ5/LeKUatxBOCNEuKXO/PV8e7pn/Hr/BqfFm+UcYrQoFdZplmtNAfqmbqgVziKvCpA==}
+    engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
+    hasBin: true
+
+  '@angular-devkit/schematics@17.3.8':
+    resolution: {integrity: sha512-QRVEYpIfgkprNHc916JlPuNbLzOgrm9DZalHasnLUz4P6g7pR21olb8YCyM2OTJjombNhya9ZpckcADU5Qyvlg==}
+    engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
+
+  '@babel/code-frame@7.24.7':
+    resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/compat-data@7.24.7':
+    resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/core@7.24.7':
+    resolution: {integrity: sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/generator@7.24.7':
+    resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-compilation-targets@7.24.7':
+    resolution: {integrity: sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-environment-visitor@7.24.7':
+    resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-function-name@7.24.7':
+    resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-hoist-variables@7.24.7':
+    resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-module-imports@7.24.7':
+    resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-module-transforms@7.24.7':
+    resolution: {integrity: sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0
+
+  '@babel/helper-plugin-utils@7.24.7':
+    resolution: {integrity: sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-simple-access@7.24.7':
+    resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-split-export-declaration@7.24.7':
+    resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-string-parser@7.24.7':
+    resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-validator-identifier@7.24.7':
+    resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-validator-option@7.24.7':
+    resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helpers@7.24.7':
+    resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/highlight@7.24.7':
+    resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/parser@7.24.7':
+    resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==}
+    engines: {node: '>=6.0.0'}
+    hasBin: true
+
+  '@babel/plugin-syntax-async-generators@7.8.4':
+    resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-bigint@7.8.3':
+    resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-class-properties@7.12.13':
+    resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-import-meta@7.10.4':
+    resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-json-strings@7.8.3':
+    resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-jsx@7.24.7':
+    resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-logical-assignment-operators@7.10.4':
+    resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3':
+    resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-numeric-separator@7.10.4':
+    resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-object-rest-spread@7.8.3':
+    resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-optional-catch-binding@7.8.3':
+    resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-optional-chaining@7.8.3':
+    resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-top-level-await@7.14.5':
+    resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-typescript@7.24.7':
+    resolution: {integrity: sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/template@7.24.7':
+    resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/traverse@7.24.7':
+    resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/types@7.24.7':
+    resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==}
+    engines: {node: '>=6.9.0'}
+
+  '@bcoe/v8-coverage@0.2.3':
+    resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
+
+  '@colors/colors@1.5.0':
+    resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
+    engines: {node: '>=0.1.90'}
+
+  '@colors/colors@1.6.0':
+    resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==}
+    engines: {node: '>=0.1.90'}
+
+  '@cspotcode/source-map-support@0.8.1':
+    resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
+    engines: {node: '>=12'}
+
+  '@dabh/diagnostics@2.0.3':
+    resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
+
+  '@eslint-community/eslint-utils@4.4.0':
+    resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+
+  '@eslint-community/regexpp@4.11.0':
+    resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==}
+    engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+
+  '@eslint/eslintrc@2.1.4':
+    resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+  '@eslint/js@8.57.0':
+    resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+  '@humanwhocodes/config-array@0.11.14':
+    resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
+    engines: {node: '>=10.10.0'}
+    deprecated: Use @eslint/config-array instead
+
+  '@humanwhocodes/module-importer@1.0.1':
+    resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+    engines: {node: '>=12.22'}
+
+  '@humanwhocodes/object-schema@2.0.3':
+    resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
+    deprecated: Use @eslint/object-schema instead
+
+  '@isaacs/cliui@8.0.2':
+    resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+    engines: {node: '>=12'}
+
+  '@istanbuljs/load-nyc-config@1.1.0':
+    resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==}
+    engines: {node: '>=8'}
+
+  '@istanbuljs/schema@0.1.3':
+    resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
+    engines: {node: '>=8'}
+
+  '@jest/console@29.7.0':
+    resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  '@jest/core@29.7.0':
+    resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+    peerDependencies:
+      node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
+    peerDependenciesMeta:
+      node-notifier:
+        optional: true
+
+  '@jest/environment@29.7.0':
+    resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  '@jest/expect-utils@29.7.0':
+    resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  '@jest/expect@29.7.0':
+    resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  '@jest/fake-timers@29.7.0':
+    resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  '@jest/globals@29.7.0':
+    resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  '@jest/reporters@29.7.0':
+    resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+    peerDependencies:
+      node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
+    peerDependenciesMeta:
+      node-notifier:
+        optional: true
+
+  '@jest/schemas@29.6.3':
+    resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  '@jest/source-map@29.6.3':
+    resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  '@jest/test-result@29.7.0':
+    resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  '@jest/test-sequencer@29.7.0':
+    resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  '@jest/transform@29.7.0':
+    resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  '@jest/types@29.6.3':
+    resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  '@jridgewell/gen-mapping@0.3.5':
+    resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
+    engines: {node: '>=6.0.0'}
+
+  '@jridgewell/resolve-uri@3.1.2':
+    resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+    engines: {node: '>=6.0.0'}
+
+  '@jridgewell/set-array@1.2.1':
+    resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
+    engines: {node: '>=6.0.0'}
+
+  '@jridgewell/source-map@0.3.6':
+    resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==}
+
+  '@jridgewell/sourcemap-codec@1.4.15':
+    resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+
+  '@jridgewell/trace-mapping@0.3.25':
+    resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+
+  '@jridgewell/trace-mapping@0.3.9':
+    resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
+
+  '@ljharb/through@2.3.13':
+    resolution: {integrity: sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==}
+    engines: {node: '>= 0.4'}
+
+  '@lukeed/csprng@1.1.0':
+    resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==}
+    engines: {node: '>=8'}
+
+  '@microsoft/tsdoc@0.15.0':
+    resolution: {integrity: sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==}
+
+  '@nestjs/axios@3.0.3':
+    resolution: {integrity: sha512-h6TCn3yJwD6OKqqqfmtRS5Zo4E46Ip2n+gK1sqwzNBC+qxQ9xpCu+ODVRFur6V3alHSCSBxb3nNtt73VEdluyA==}
+    peerDependencies:
+      '@nestjs/common': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0
+      axios: ^1.3.1
+      rxjs: ^6.0.0 || ^7.0.0
+
+  '@nestjs/cli@10.4.2':
+    resolution: {integrity: sha512-fQexIfLHfp6GUgX+CO4fOg+AEwV5ox/LHotQhyZi9wXUQDyIqS0NTTbumr//62EcX35qV4nU0359nYnuEdzG+A==}
+    engines: {node: '>= 16.14'}
+    hasBin: true
+    peerDependencies:
+      '@swc/cli': ^0.1.62 || ^0.3.0 || ^0.4.0
+      '@swc/core': ^1.3.62
+    peerDependenciesMeta:
+      '@swc/cli':
+        optional: true
+      '@swc/core':
+        optional: true
+
+  '@nestjs/common@10.3.10':
+    resolution: {integrity: sha512-H8k0jZtxk1IdtErGDmxFRy0PfcOAUg41Prrqpx76DQusGGJjsaovs1zjXVD1rZWaVYchfT1uczJ6L4Kio10VNg==}
+    peerDependencies:
+      class-transformer: '*'
+      class-validator: '*'
+      reflect-metadata: ^0.1.12 || ^0.2.0
+      rxjs: ^7.1.0
+    peerDependenciesMeta:
+      class-transformer:
+        optional: true
+      class-validator:
+        optional: true
+
+  '@nestjs/core@10.3.10':
+    resolution: {integrity: sha512-ZbQ4jovQyzHtCGCrzK5NdtW1SYO2fHSsgSY1+/9WdruYCUra+JDkWEXgZ4M3Hv480Dl3OXehAmY1wCOojeMyMQ==}
+    peerDependencies:
+      '@nestjs/common': ^10.0.0
+      '@nestjs/microservices': ^10.0.0
+      '@nestjs/platform-express': ^10.0.0
+      '@nestjs/websockets': ^10.0.0
+      reflect-metadata: ^0.1.12 || ^0.2.0
+      rxjs: ^7.1.0
+    peerDependenciesMeta:
+      '@nestjs/microservices':
+        optional: true
+      '@nestjs/platform-express':
+        optional: true
+      '@nestjs/websockets':
+        optional: true
+
+  '@nestjs/event-emitter@2.0.4':
+    resolution: {integrity: sha512-quMiw8yOwoSul0pp3mOonGz8EyXWHSBTqBy8B0TbYYgpnG1Ix2wGUnuTksLWaaBiiOTDhciaZ41Y5fJZsSJE1Q==}
+    peerDependencies:
+      '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0
+      '@nestjs/core': ^8.0.0 || ^9.0.0 || ^10.0.0
+
+  '@nestjs/jwt@10.2.0':
+    resolution: {integrity: sha512-x8cG90SURkEiLOehNaN2aRlotxT0KZESUliOPKKnjWiyJOcWurkF3w345WOX0P4MgFzUjGoZ1Sy0aZnxeihT0g==}
+    peerDependencies:
+      '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0
+
+  '@nestjs/mapped-types@2.0.5':
+    resolution: {integrity: sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==}
+    peerDependencies:
+      '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0
+      class-transformer: ^0.4.0 || ^0.5.0
+      class-validator: ^0.13.0 || ^0.14.0
+      reflect-metadata: ^0.1.12 || ^0.2.0
+    peerDependenciesMeta:
+      class-transformer:
+        optional: true
+      class-validator:
+        optional: true
+
+  '@nestjs/passport@10.0.3':
+    resolution: {integrity: sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ==}
+    peerDependencies:
+      '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0
+      passport: ^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0
+
+  '@nestjs/platform-express@10.3.10':
+    resolution: {integrity: sha512-wK2ow3CZI2KFqWeEpPmoR300OB6BcBLxARV1EiClJLCj4S1mZsoCmS0YWgpk3j1j6mo0SI8vNLi/cC2iZPEPQA==}
+    peerDependencies:
+      '@nestjs/common': ^10.0.0
+      '@nestjs/core': ^10.0.0
+
+  '@nestjs/schematics@10.1.2':
+    resolution: {integrity: sha512-S0bMtZM5U4mAiqkhRyZkXgjmOHBS5P/lp/vEydgMR4F7csOShc3jFeKVs1Eghd9xCFezGKy3SHy7hFT6dpPhWQ==}
+    peerDependencies:
+      typescript: '>=4.8.2'
+
+  '@nestjs/swagger@7.4.0':
+    resolution: {integrity: sha512-dCiwKkRxcR7dZs5jtrGspBAe/nqJd1AYzOBTzw9iCdbq3BGrLpwokelk6lFZPe4twpTsPQqzNKBwKzVbI6AR/g==}
+    peerDependencies:
+      '@fastify/static': ^6.0.0 || ^7.0.0
+      '@nestjs/common': ^9.0.0 || ^10.0.0
+      '@nestjs/core': ^9.0.0 || ^10.0.0
+      class-transformer: '*'
+      class-validator: '*'
+      reflect-metadata: ^0.1.12 || ^0.2.0
+    peerDependenciesMeta:
+      '@fastify/static':
+        optional: true
+      class-transformer:
+        optional: true
+      class-validator:
+        optional: true
+
+  '@nestjs/testing@10.3.10':
+    resolution: {integrity: sha512-i3HAtVQJijxNxJq1k39aelyJlyEIBRONys7IipH/4r8W0J+M1V+y5EKDOyi4j1SdNSb/vmNyWpZ2/ewZjl3kRA==}
+    peerDependencies:
+      '@nestjs/common': ^10.0.0
+      '@nestjs/core': ^10.0.0
+      '@nestjs/microservices': ^10.0.0
+      '@nestjs/platform-express': ^10.0.0
+    peerDependenciesMeta:
+      '@nestjs/microservices':
+        optional: true
+      '@nestjs/platform-express':
+        optional: true
+
+  '@nodelib/fs.scandir@2.1.5':
+    resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+    engines: {node: '>= 8'}
+
+  '@nodelib/fs.stat@2.0.5':
+    resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+    engines: {node: '>= 8'}
+
+  '@nodelib/fs.walk@1.2.8':
+    resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+    engines: {node: '>= 8'}
+
+  '@nuxtjs/opencollective@0.3.2':
+    resolution: {integrity: sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==}
+    engines: {node: '>=8.0.0', npm: '>=5.0.0'}
+    hasBin: true
+
+  '@pkgjs/parseargs@0.11.0':
+    resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+    engines: {node: '>=14'}
+
+  '@pkgr/core@0.1.1':
+    resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==}
+    engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+
+  '@prisma/client@5.16.1':
+    resolution: {integrity: sha512-wM9SKQjF0qLxdnOZIVAIMKiz6Hu7vDt4FFAih85K1dk/Rr2mdahy6d3QP41K62N9O0DJJA//gUDA3Mp49xsKIg==}
+    engines: {node: '>=16.13'}
+    peerDependencies:
+      prisma: '*'
+    peerDependenciesMeta:
+      prisma:
+        optional: true
+
+  '@prisma/debug@5.16.1':
+    resolution: {integrity: sha512-JsNgZAg6BD9RInLSrg7ZYzo11N7cVvYArq3fHGSD89HSgtN0VDdjV6bib7YddbcO6snzjchTiLfjeTqBjtArVQ==}
+
+  '@prisma/engines-version@5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303':
+    resolution: {integrity: sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw==}
+
+  '@prisma/engines@5.16.1':
+    resolution: {integrity: sha512-KkyF3eIUtBIyp5A/rJHCtwQO18OjpGgx18PzjyGcJDY/+vNgaVyuVd+TgwBgeq6NLdd1XMwRCI+58vinHsAdfA==}
+
+  '@prisma/fetch-engine@5.16.1':
+    resolution: {integrity: sha512-oOkjaPU1lhcA/Rvr4GVfd1NLJBwExgNBE36Ueq7dr71kTMwy++a3U3oLd2ZwrV9dj9xoP6LjCcky799D9nEt4w==}
+
+  '@prisma/get-platform@5.16.1':
+    resolution: {integrity: sha512-R4IKnWnMkR2nUAbU5gjrPehdQYUUd7RENFD2/D+xXTNhcqczp0N+WEGQ3ViyI3+6mtVcjjNIMdnUTNyu3GxIgA==}
+
+  '@sinclair/typebox@0.27.8':
+    resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
+
+  '@sinonjs/commons@3.0.1':
+    resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==}
+
+  '@sinonjs/fake-timers@10.3.0':
+    resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==}
+
+  '@tsconfig/node10@1.0.11':
+    resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
+
+  '@tsconfig/node12@1.0.11':
+    resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
+
+  '@tsconfig/node14@1.0.3':
+    resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
+
+  '@tsconfig/node16@1.0.4':
+    resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
+
+  '@types/babel__core@7.20.5':
+    resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+  '@types/babel__generator@7.6.8':
+    resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==}
+
+  '@types/babel__template@7.4.4':
+    resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+  '@types/babel__traverse@7.20.6':
+    resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==}
+
+  '@types/body-parser@1.19.5':
+    resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
+
+  '@types/connect@3.4.38':
+    resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
+
+  '@types/cookiejar@2.1.5':
+    resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==}
+
+  '@types/eslint-scope@3.7.7':
+    resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==}
+
+  '@types/eslint@8.56.10':
+    resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==}
+
+  '@types/estree@1.0.5':
+    resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
+
+  '@types/express-serve-static-core@4.19.5':
+    resolution: {integrity: sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==}
+
+  '@types/express-session@1.18.0':
+    resolution: {integrity: sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==}
+
+  '@types/express@4.17.21':
+    resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==}
+
+  '@types/graceful-fs@4.1.9':
+    resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
+
+  '@types/http-errors@2.0.4':
+    resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
+
+  '@types/istanbul-lib-coverage@2.0.6':
+    resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
+
+  '@types/istanbul-lib-report@3.0.3':
+    resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==}
+
+  '@types/istanbul-reports@3.0.4':
+    resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==}
+
+  '@types/jest@29.5.12':
+    resolution: {integrity: sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==}
+
+  '@types/json-schema@7.0.15':
+    resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+
+  '@types/jsonwebtoken@9.0.5':
+    resolution: {integrity: sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==}
+
+  '@types/methods@1.1.4':
+    resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==}
+
+  '@types/mime@1.3.5':
+    resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
+
+  '@types/multer@1.4.11':
+    resolution: {integrity: sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==}
+
+  '@types/node@20.14.10':
+    resolution: {integrity: sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==}
+
+  '@types/qs@6.9.15':
+    resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==}
+
+  '@types/range-parser@1.2.7':
+    resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
+
+  '@types/send@0.17.4':
+    resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==}
+
+  '@types/serve-static@1.15.7':
+    resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==}
+
+  '@types/stack-utils@2.0.3':
+    resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
+
+  '@types/superagent@8.1.7':
+    resolution: {integrity: sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww==}
+
+  '@types/supertest@6.0.2':
+    resolution: {integrity: sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==}
+
+  '@types/triple-beam@1.3.5':
+    resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==}
+
+  '@types/validator@13.12.0':
+    resolution: {integrity: sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==}
+
+  '@types/yargs-parser@21.0.3':
+    resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
+
+  '@types/yargs@17.0.32':
+    resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==}
+
+  '@typescript-eslint/eslint-plugin@7.16.0':
+    resolution: {integrity: sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      '@typescript-eslint/parser': ^7.0.0
+      eslint: ^8.56.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
+  '@typescript-eslint/parser@7.16.0':
+    resolution: {integrity: sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
+  '@typescript-eslint/scope-manager@7.16.0':
+    resolution: {integrity: sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+
+  '@typescript-eslint/type-utils@7.16.0':
+    resolution: {integrity: sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
+  '@typescript-eslint/types@7.16.0':
+    resolution: {integrity: sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+
+  '@typescript-eslint/typescript-estree@7.16.0':
+    resolution: {integrity: sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
+  '@typescript-eslint/utils@7.16.0':
+    resolution: {integrity: sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+
+  '@typescript-eslint/visitor-keys@7.16.0':
+    resolution: {integrity: sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+
+  '@ungap/structured-clone@1.2.0':
+    resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
+
+  '@webassemblyjs/ast@1.12.1':
+    resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==}
+
+  '@webassemblyjs/floating-point-hex-parser@1.11.6':
+    resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==}
+
+  '@webassemblyjs/helper-api-error@1.11.6':
+    resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==}
+
+  '@webassemblyjs/helper-buffer@1.12.1':
+    resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==}
+
+  '@webassemblyjs/helper-numbers@1.11.6':
+    resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==}
+
+  '@webassemblyjs/helper-wasm-bytecode@1.11.6':
+    resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==}
+
+  '@webassemblyjs/helper-wasm-section@1.12.1':
+    resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==}
+
+  '@webassemblyjs/ieee754@1.11.6':
+    resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==}
+
+  '@webassemblyjs/leb128@1.11.6':
+    resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==}
+
+  '@webassemblyjs/utf8@1.11.6':
+    resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==}
+
+  '@webassemblyjs/wasm-edit@1.12.1':
+    resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==}
+
+  '@webassemblyjs/wasm-gen@1.12.1':
+    resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==}
+
+  '@webassemblyjs/wasm-opt@1.12.1':
+    resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==}
+
+  '@webassemblyjs/wasm-parser@1.12.1':
+    resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==}
+
+  '@webassemblyjs/wast-printer@1.12.1':
+    resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==}
+
+  '@xtuc/ieee754@1.2.0':
+    resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==}
+
+  '@xtuc/long@4.2.2':
+    resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==}
+
+  accepts@1.3.8:
+    resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
+    engines: {node: '>= 0.6'}
+
+  acorn-import-attributes@1.9.5:
+    resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==}
+    peerDependencies:
+      acorn: ^8
+
+  acorn-jsx@5.3.2:
+    resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+    peerDependencies:
+      acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
+  acorn-walk@8.3.3:
+    resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==}
+    engines: {node: '>=0.4.0'}
+
+  acorn@8.12.1:
+    resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==}
+    engines: {node: '>=0.4.0'}
+    hasBin: true
+
+  adler-32@1.3.1:
+    resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==}
+    engines: {node: '>=0.8'}
+
+  ajv-formats@2.1.1:
+    resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
+    peerDependencies:
+      ajv: ^8.0.0
+    peerDependenciesMeta:
+      ajv:
+        optional: true
+
+  ajv-keywords@3.5.2:
+    resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==}
+    peerDependencies:
+      ajv: ^6.9.1
+
+  ajv@6.12.6:
+    resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+
+  ajv@8.12.0:
+    resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==}
+
+  ansi-colors@4.1.3:
+    resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
+    engines: {node: '>=6'}
+
+  ansi-escapes@4.3.2:
+    resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
+    engines: {node: '>=8'}
+
+  ansi-regex@5.0.1:
+    resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+    engines: {node: '>=8'}
+
+  ansi-regex@6.0.1:
+    resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
+    engines: {node: '>=12'}
+
+  ansi-styles@3.2.1:
+    resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+    engines: {node: '>=4'}
+
+  ansi-styles@4.3.0:
+    resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+    engines: {node: '>=8'}
+
+  ansi-styles@5.2.0:
+    resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
+    engines: {node: '>=10'}
+
+  ansi-styles@6.2.1:
+    resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+    engines: {node: '>=12'}
+
+  anymatch@3.1.3:
+    resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+    engines: {node: '>= 8'}
+
+  append-field@1.0.0:
+    resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==}
+
+  arg@4.1.3:
+    resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
+
+  argparse@1.0.10:
+    resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
+
+  argparse@2.0.1:
+    resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
+  array-flatten@1.1.1:
+    resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
+
+  array-timsort@1.0.3:
+    resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==}
+
+  array-union@2.1.0:
+    resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+    engines: {node: '>=8'}
+
+  asap@2.0.6:
+    resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==}
+
+  async@3.2.6:
+    resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
+
+  asynckit@0.4.0:
+    resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+  axios@1.7.4:
+    resolution: {integrity: sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==}
+
+  babel-jest@29.7.0:
+    resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+    peerDependencies:
+      '@babel/core': ^7.8.0
+
+  babel-plugin-istanbul@6.1.1:
+    resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==}
+    engines: {node: '>=8'}
+
+  babel-plugin-jest-hoist@29.6.3:
+    resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  babel-preset-current-node-syntax@1.0.1:
+    resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==}
+    peerDependencies:
+      '@babel/core': ^7.0.0
+
+  babel-preset-jest@29.6.3:
+    resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+    peerDependencies:
+      '@babel/core': ^7.0.0
+
+  balanced-match@1.0.2:
+    resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+  base64-js@1.5.1:
+    resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
+  bcryptjs@3.0.2:
+    resolution: {integrity: sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==}
+    hasBin: true
+
+  binary-extensions@2.3.0:
+    resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
+    engines: {node: '>=8'}
+
+  bl@4.1.0:
+    resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
+
+  body-parser@1.20.2:
+    resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==}
+    engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
+
+  brace-expansion@1.1.11:
+    resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+
+  brace-expansion@2.0.1:
+    resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+
+  braces@3.0.3:
+    resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+    engines: {node: '>=8'}
+
+  browserslist@4.23.1:
+    resolution: {integrity: sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==}
+    engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+    hasBin: true
+
+  bs-logger@0.2.6:
+    resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==}
+    engines: {node: '>= 6'}
+
+  bser@2.1.1:
+    resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
+
+  buffer-equal-constant-time@1.0.1:
+    resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
+
+  buffer-from@1.1.2:
+    resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+
+  buffer@5.7.1:
+    resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
+
+  busboy@1.6.0:
+    resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
+    engines: {node: '>=10.16.0'}
+
+  bytes@3.1.2:
+    resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
+    engines: {node: '>= 0.8'}
+
+  call-bind@1.0.7:
+    resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==}
+    engines: {node: '>= 0.4'}
+
+  callsites@3.1.0:
+    resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+    engines: {node: '>=6'}
+
+  camelcase@5.3.1:
+    resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
+    engines: {node: '>=6'}
+
+  camelcase@6.3.0:
+    resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
+    engines: {node: '>=10'}
+
+  caniuse-lite@1.0.30001640:
+    resolution: {integrity: sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==}
+
+  cfb@1.2.2:
+    resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==}
+    engines: {node: '>=0.8'}
+
+  chalk@2.4.2:
+    resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+    engines: {node: '>=4'}
+
+  chalk@4.1.2:
+    resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+    engines: {node: '>=10'}
+
+  chalk@5.3.0:
+    resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
+    engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+
+  char-regex@1.0.2:
+    resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
+    engines: {node: '>=10'}
+
+  chardet@0.7.0:
+    resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
+
+  chokidar@3.6.0:
+    resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
+    engines: {node: '>= 8.10.0'}
+
+  chrome-trace-event@1.0.4:
+    resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==}
+    engines: {node: '>=6.0'}
+
+  ci-info@3.9.0:
+    resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
+    engines: {node: '>=8'}
+
+  cjs-module-lexer@1.3.1:
+    resolution: {integrity: sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==}
+
+  class-transformer@0.5.1:
+    resolution: {integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==}
+
+  class-validator@0.14.1:
+    resolution: {integrity: sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==}
+
+  cli-cursor@3.1.0:
+    resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
+    engines: {node: '>=8'}
+
+  cli-spinners@2.9.2:
+    resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
+    engines: {node: '>=6'}
+
+  cli-table3@0.6.5:
+    resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==}
+    engines: {node: 10.* || >= 12.*}
+
+  cli-width@3.0.0:
+    resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==}
+    engines: {node: '>= 10'}
+
+  cli-width@4.1.0:
+    resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
+    engines: {node: '>= 12'}
+
+  cliui@8.0.1:
+    resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+    engines: {node: '>=12'}
+
+  clone@1.0.4:
+    resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
+    engines: {node: '>=0.8'}
+
+  co@4.6.0:
+    resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==}
+    engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'}
+
+  codepage@1.15.0:
+    resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==}
+    engines: {node: '>=0.8'}
+
+  collect-v8-coverage@1.0.2:
+    resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==}
+
+  color-convert@1.9.3:
+    resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+
+  color-convert@2.0.1:
+    resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+    engines: {node: '>=7.0.0'}
+
+  color-name@1.1.3:
+    resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+
+  color-name@1.1.4:
+    resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+  color-string@1.9.1:
+    resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
+
+  color@3.2.1:
+    resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==}
+
+  colorspace@1.1.4:
+    resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==}
+
+  combined-stream@1.0.8:
+    resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+    engines: {node: '>= 0.8'}
+
+  commander@2.20.3:
+    resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+
+  commander@4.1.1:
+    resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+    engines: {node: '>= 6'}
+
+  comment-json@4.2.3:
+    resolution: {integrity: sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==}
+    engines: {node: '>= 6'}
+
+  component-emitter@1.3.1:
+    resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==}
+
+  concat-map@0.0.1:
+    resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
+  concat-stream@1.6.2:
+    resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==}
+    engines: {'0': node >= 0.8}
+
+  consola@2.15.3:
+    resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==}
+
+  content-disposition@0.5.4:
+    resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
+    engines: {node: '>= 0.6'}
+
+  content-type@1.0.5:
+    resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
+    engines: {node: '>= 0.6'}
+
+  convert-source-map@2.0.0:
+    resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+  cookie-signature@1.0.6:
+    resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
+
+  cookie-signature@1.0.7:
+    resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==}
+
+  cookie@0.6.0:
+    resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
+    engines: {node: '>= 0.6'}
+
+  cookiejar@2.1.4:
+    resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==}
+
+  core-util-is@1.0.3:
+    resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
+
+  cors@2.8.5:
+    resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
+    engines: {node: '>= 0.10'}
+
+  cosmiconfig@8.3.6:
+    resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      typescript: '>=4.9.5'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
+  crc-32@1.2.2:
+    resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
+    engines: {node: '>=0.8'}
+    hasBin: true
+
+  create-jest@29.7.0:
+    resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+    hasBin: true
+
+  create-require@1.1.1:
+    resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
+
+  cross-spawn@7.0.3:
+    resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+    engines: {node: '>= 8'}
+
+  dayjs@1.11.11:
+    resolution: {integrity: sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==}
+
+  debug@2.6.9:
+    resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+
+  debug@4.3.5:
+    resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==}
+    engines: {node: '>=6.0'}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+
+  dedent@1.5.3:
+    resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==}
+    peerDependencies:
+      babel-plugin-macros: ^3.1.0
+    peerDependenciesMeta:
+      babel-plugin-macros:
+        optional: true
+
+  deep-is@0.1.4:
+    resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+
+  deepmerge@4.3.1:
+    resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
+    engines: {node: '>=0.10.0'}
+
+  defaults@1.0.4:
+    resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
+
+  define-data-property@1.1.4:
+    resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
+    engines: {node: '>= 0.4'}
+
+  delayed-stream@1.0.0:
+    resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+    engines: {node: '>=0.4.0'}
+
+  depd@2.0.0:
+    resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+    engines: {node: '>= 0.8'}
+
+  destroy@1.2.0:
+    resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
+    engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
+
+  detect-newline@3.1.0:
+    resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
+    engines: {node: '>=8'}
+
+  dezalgo@1.0.4:
+    resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==}
+
+  diff-sequences@29.6.3:
+    resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  diff@4.0.2:
+    resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
+    engines: {node: '>=0.3.1'}
+
+  dir-glob@3.0.1:
+    resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+    engines: {node: '>=8'}
+
+  doctrine@3.0.0:
+    resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+    engines: {node: '>=6.0.0'}
+
+  eastasianwidth@0.2.0:
+    resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+
+  ecdsa-sig-formatter@1.0.11:
+    resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
+
+  ee-first@1.1.1:
+    resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+
+  electron-to-chromium@1.4.819:
+    resolution: {integrity: sha512-8RwI6gKUokbHWcN3iRij/qpvf/wCbIVY5slODi85werwqUQwpFXM+dvUBND93Qh7SB0pW3Hlq3/wZsqQ3M9Jaw==}
+
+  emittery@0.13.1:
+    resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==}
+    engines: {node: '>=12'}
+
+  emoji-regex@8.0.0:
+    resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
+  emoji-regex@9.2.2:
+    resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+
+  enabled@2.0.0:
+    resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==}
+
+  encodeurl@1.0.2:
+    resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
+    engines: {node: '>= 0.8'}
+
+  enhanced-resolve@5.17.0:
+    resolution: {integrity: sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==}
+    engines: {node: '>=10.13.0'}
+
+  enhanced-resolve@5.17.1:
+    resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==}
+    engines: {node: '>=10.13.0'}
+
+  error-ex@1.3.2:
+    resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
+
+  es-define-property@1.0.0:
+    resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==}
+    engines: {node: '>= 0.4'}
+
+  es-errors@1.3.0:
+    resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+    engines: {node: '>= 0.4'}
+
+  es-module-lexer@1.5.4:
+    resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
+
+  escalade@3.1.2:
+    resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
+    engines: {node: '>=6'}
+
+  escape-html@1.0.3:
+    resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+
+  escape-string-regexp@1.0.5:
+    resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+    engines: {node: '>=0.8.0'}
+
+  escape-string-regexp@2.0.0:
+    resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==}
+    engines: {node: '>=8'}
+
+  escape-string-regexp@4.0.0:
+    resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+    engines: {node: '>=10'}
+
+  eslint-config-prettier@9.1.0:
+    resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==}
+    hasBin: true
+    peerDependencies:
+      eslint: '>=7.0.0'
+
+  eslint-plugin-prettier@5.1.3:
+    resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+    peerDependencies:
+      '@types/eslint': '>=8.0.0'
+      eslint: '>=8.0.0'
+      eslint-config-prettier: '*'
+      prettier: '>=3.0.0'
+    peerDependenciesMeta:
+      '@types/eslint':
+        optional: true
+      eslint-config-prettier:
+        optional: true
+
+  eslint-plugin-simple-import-sort@12.1.1:
+    resolution: {integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==}
+    peerDependencies:
+      eslint: '>=5.0.0'
+
+  eslint-scope@5.1.1:
+    resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
+    engines: {node: '>=8.0.0'}
+
+  eslint-scope@7.2.2:
+    resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+  eslint-visitor-keys@3.4.3:
+    resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+  eslint@8.57.0:
+    resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    hasBin: true
+
+  espree@9.6.1:
+    resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+  esprima@4.0.1:
+    resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
+    engines: {node: '>=4'}
+    hasBin: true
+
+  esquery@1.6.0:
+    resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
+    engines: {node: '>=0.10'}
+
+  esrecurse@4.3.0:
+    resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+    engines: {node: '>=4.0'}
+
+  estraverse@4.3.0:
+    resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==}
+    engines: {node: '>=4.0'}
+
+  estraverse@5.3.0:
+    resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+    engines: {node: '>=4.0'}
+
+  esutils@2.0.3:
+    resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+    engines: {node: '>=0.10.0'}
+
+  etag@1.8.1:
+    resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
+    engines: {node: '>= 0.6'}
+
+  eventemitter2@6.4.9:
+    resolution: {integrity: sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==}
+
+  events@3.3.0:
+    resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
+    engines: {node: '>=0.8.x'}
+
+  execa@5.1.1:
+    resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
+    engines: {node: '>=10'}
+
+  exit@0.1.2:
+    resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==}
+    engines: {node: '>= 0.8.0'}
+
+  expect@29.7.0:
+    resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  express-session@1.18.0:
+    resolution: {integrity: sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==}
+    engines: {node: '>= 0.8.0'}
+
+  express@4.19.2:
+    resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==}
+    engines: {node: '>= 0.10.0'}
+
+  external-editor@3.1.0:
+    resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==}
+    engines: {node: '>=4'}
+
+  fast-deep-equal@3.1.3:
+    resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+  fast-diff@1.3.0:
+    resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
+
+  fast-glob@3.3.2:
+    resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
+    engines: {node: '>=8.6.0'}
+
+  fast-json-stable-stringify@2.1.0:
+    resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+
+  fast-levenshtein@2.0.6:
+    resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+
+  fast-safe-stringify@2.1.1:
+    resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
+
+  fastq@1.17.1:
+    resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
+
+  fb-watchman@2.0.2:
+    resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==}
+
+  fecha@4.2.3:
+    resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==}
+
+  figures@3.2.0:
+    resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==}
+    engines: {node: '>=8'}
+
+  file-entry-cache@6.0.1:
+    resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
+    engines: {node: ^10.12.0 || >=12.0.0}
+
+  file-stream-rotator@0.6.1:
+    resolution: {integrity: sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==}
+
+  fill-range@7.1.1:
+    resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+    engines: {node: '>=8'}
+
+  finalhandler@1.2.0:
+    resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==}
+    engines: {node: '>= 0.8'}
+
+  find-up@4.1.0:
+    resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
+    engines: {node: '>=8'}
+
+  find-up@5.0.0:
+    resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+    engines: {node: '>=10'}
+
+  flat-cache@3.2.0:
+    resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
+    engines: {node: ^10.12.0 || >=12.0.0}
+
+  flatted@3.3.1:
+    resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
+
+  fn.name@1.1.0:
+    resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
+
+  follow-redirects@1.15.6:
+    resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
+    engines: {node: '>=4.0'}
+    peerDependencies:
+      debug: '*'
+    peerDependenciesMeta:
+      debug:
+        optional: true
+
+  foreground-child@3.2.1:
+    resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==}
+    engines: {node: '>=14'}
+
+  fork-ts-checker-webpack-plugin@9.0.2:
+    resolution: {integrity: sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==}
+    engines: {node: '>=12.13.0', yarn: '>=1.0.0'}
+    peerDependencies:
+      typescript: '>3.6.0'
+      webpack: ^5.11.0
+
+  form-data@4.0.0:
+    resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
+    engines: {node: '>= 6'}
+
+  formidable@3.5.1:
+    resolution: {integrity: sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==}
+
+  forwarded@0.2.0:
+    resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
+    engines: {node: '>= 0.6'}
+
+  frac@1.1.2:
+    resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==}
+    engines: {node: '>=0.8'}
+
+  fresh@0.5.2:
+    resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
+    engines: {node: '>= 0.6'}
+
+  fs-extra@10.1.0:
+    resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
+    engines: {node: '>=12'}
+
+  fs-monkey@1.0.6:
+    resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==}
+
+  fs.realpath@1.0.0:
+    resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+
+  fsevents@2.3.3:
+    resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+    engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+    os: [darwin]
+
+  function-bind@1.1.2:
+    resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+  gensync@1.0.0-beta.2:
+    resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+    engines: {node: '>=6.9.0'}
+
+  get-caller-file@2.0.5:
+    resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+    engines: {node: 6.* || 8.* || >= 10.*}
+
+  get-intrinsic@1.2.4:
+    resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
+    engines: {node: '>= 0.4'}
+
+  get-package-type@0.1.0:
+    resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
+    engines: {node: '>=8.0.0'}
+
+  get-stream@6.0.1:
+    resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+    engines: {node: '>=10'}
+
+  glob-parent@5.1.2:
+    resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+    engines: {node: '>= 6'}
+
+  glob-parent@6.0.2:
+    resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+    engines: {node: '>=10.13.0'}
+
+  glob-to-regexp@0.4.1:
+    resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
+
+  glob@10.4.2:
+    resolution: {integrity: sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==}
+    engines: {node: '>=16 || 14 >=14.18'}
+    hasBin: true
+
+  glob@7.2.3:
+    resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+    deprecated: Glob versions prior to v9 are no longer supported
+
+  globals@11.12.0:
+    resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
+    engines: {node: '>=4'}
+
+  globals@13.24.0:
+    resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
+    engines: {node: '>=8'}
+
+  globby@11.1.0:
+    resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
+    engines: {node: '>=10'}
+
+  gopd@1.0.1:
+    resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
+
+  graceful-fs@4.2.11:
+    resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+  graphemer@1.4.0:
+    resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+
+  has-flag@3.0.0:
+    resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+    engines: {node: '>=4'}
+
+  has-flag@4.0.0:
+    resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+    engines: {node: '>=8'}
+
+  has-own-prop@2.0.0:
+    resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==}
+    engines: {node: '>=8'}
+
+  has-property-descriptors@1.0.2:
+    resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
+
+  has-proto@1.0.3:
+    resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==}
+    engines: {node: '>= 0.4'}
+
+  has-symbols@1.0.3:
+    resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
+    engines: {node: '>= 0.4'}
+
+  hasown@2.0.2:
+    resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+    engines: {node: '>= 0.4'}
+
+  hexoid@1.0.0:
+    resolution: {integrity: sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==}
+    engines: {node: '>=8'}
+
+  html-escaper@2.0.2:
+    resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+
+  http-errors@2.0.0:
+    resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
+    engines: {node: '>= 0.8'}
+
+  human-signals@2.1.0:
+    resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
+    engines: {node: '>=10.17.0'}
+
+  iconv-lite@0.4.24:
+    resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
+    engines: {node: '>=0.10.0'}
+
+  ieee754@1.2.1:
+    resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+
+  ignore@5.3.1:
+    resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
+    engines: {node: '>= 4'}
+
+  import-fresh@3.3.0:
+    resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+    engines: {node: '>=6'}
+
+  import-local@3.1.0:
+    resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==}
+    engines: {node: '>=8'}
+    hasBin: true
+
+  imurmurhash@0.1.4:
+    resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+    engines: {node: '>=0.8.19'}
+
+  inflight@1.0.6:
+    resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+    deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
+
+  inherits@2.0.4:
+    resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+  inquirer@8.2.6:
+    resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==}
+    engines: {node: '>=12.0.0'}
+
+  inquirer@9.2.15:
+    resolution: {integrity: sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==}
+    engines: {node: '>=18'}
+
+  ipaddr.js@1.9.1:
+    resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
+    engines: {node: '>= 0.10'}
+
+  is-arrayish@0.2.1:
+    resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
+
+  is-arrayish@0.3.2:
+    resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
+
+  is-binary-path@2.1.0:
+    resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+    engines: {node: '>=8'}
+
+  is-core-module@2.14.0:
+    resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==}
+    engines: {node: '>= 0.4'}
+
+  is-extglob@2.1.1:
+    resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+    engines: {node: '>=0.10.0'}
+
+  is-fullwidth-code-point@3.0.0:
+    resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+    engines: {node: '>=8'}
+
+  is-generator-fn@2.1.0:
+    resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==}
+    engines: {node: '>=6'}
+
+  is-glob@4.0.3:
+    resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+    engines: {node: '>=0.10.0'}
+
+  is-interactive@1.0.0:
+    resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
+    engines: {node: '>=8'}
+
+  is-number@7.0.0:
+    resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+    engines: {node: '>=0.12.0'}
+
+  is-path-inside@3.0.3:
+    resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+    engines: {node: '>=8'}
+
+  is-stream@2.0.1:
+    resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+    engines: {node: '>=8'}
+
+  is-unicode-supported@0.1.0:
+    resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
+    engines: {node: '>=10'}
+
+  isarray@1.0.0:
+    resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
+
+  isexe@2.0.0:
+    resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+  istanbul-lib-coverage@3.2.2:
+    resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
+    engines: {node: '>=8'}
+
+  istanbul-lib-instrument@5.2.1:
+    resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==}
+    engines: {node: '>=8'}
+
+  istanbul-lib-instrument@6.0.3:
+    resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==}
+    engines: {node: '>=10'}
+
+  istanbul-lib-report@3.0.1:
+    resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
+    engines: {node: '>=10'}
+
+  istanbul-lib-source-maps@4.0.1:
+    resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==}
+    engines: {node: '>=10'}
+
+  istanbul-reports@3.1.7:
+    resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==}
+    engines: {node: '>=8'}
+
+  iterare@1.2.1:
+    resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==}
+    engines: {node: '>=6'}
+
+  jackspeak@3.4.2:
+    resolution: {integrity: sha512-qH3nOSj8q/8+Eg8LUPOq3C+6HWkpUioIjDsq1+D4zY91oZvpPttw8GwtF1nReRYKXl+1AORyFqtm2f5Q1SB6/Q==}
+    engines: {node: 14 >=14.21 || 16 >=16.20 || >=18}
+
+  jest-changed-files@29.7.0:
+    resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-circus@29.7.0:
+    resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-cli@29.7.0:
+    resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+    hasBin: true
+    peerDependencies:
+      node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
+    peerDependenciesMeta:
+      node-notifier:
+        optional: true
+
+  jest-config@29.7.0:
+    resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+    peerDependencies:
+      '@types/node': '*'
+      ts-node: '>=9.0.0'
+    peerDependenciesMeta:
+      '@types/node':
+        optional: true
+      ts-node:
+        optional: true
+
+  jest-diff@29.7.0:
+    resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-docblock@29.7.0:
+    resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-each@29.7.0:
+    resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-environment-node@29.7.0:
+    resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-get-type@29.6.3:
+    resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-haste-map@29.7.0:
+    resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-leak-detector@29.7.0:
+    resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-matcher-utils@29.7.0:
+    resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-message-util@29.7.0:
+    resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-mock@29.7.0:
+    resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-pnp-resolver@1.2.3:
+    resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==}
+    engines: {node: '>=6'}
+    peerDependencies:
+      jest-resolve: '*'
+    peerDependenciesMeta:
+      jest-resolve:
+        optional: true
+
+  jest-regex-util@29.6.3:
+    resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-resolve-dependencies@29.7.0:
+    resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-resolve@29.7.0:
+    resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-runner@29.7.0:
+    resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-runtime@29.7.0:
+    resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-snapshot@29.7.0:
+    resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-util@29.7.0:
+    resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-validate@29.7.0:
+    resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-watcher@29.7.0:
+    resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest-worker@27.5.1:
+    resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
+    engines: {node: '>= 10.13.0'}
+
+  jest-worker@29.7.0:
+    resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  jest@29.7.0:
+    resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+    hasBin: true
+    peerDependencies:
+      node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
+    peerDependenciesMeta:
+      node-notifier:
+        optional: true
+
+  js-tokens@4.0.0:
+    resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+  js-yaml@3.14.1:
+    resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
+    hasBin: true
+
+  js-yaml@4.1.0:
+    resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+    hasBin: true
+
+  jsesc@2.5.2:
+    resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
+    engines: {node: '>=4'}
+    hasBin: true
+
+  json-buffer@3.0.1:
+    resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+
+  json-parse-even-better-errors@2.3.1:
+    resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
+
+  json-schema-traverse@0.4.1:
+    resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+
+  json-schema-traverse@1.0.0:
+    resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
+
+  json-stable-stringify-without-jsonify@1.0.1:
+    resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+
+  json5@2.2.3:
+    resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+    engines: {node: '>=6'}
+    hasBin: true
+
+  jsonc-parser@3.2.1:
+    resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==}
+
+  jsonc-parser@3.3.1:
+    resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==}
+
+  jsonfile@6.1.0:
+    resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
+
+  jsonwebtoken@9.0.2:
+    resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
+    engines: {node: '>=12', npm: '>=6'}
+
+  jwa@1.4.1:
+    resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==}
+
+  jws@3.2.2:
+    resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
+
+  keyv@4.5.4:
+    resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+
+  kleur@3.0.3:
+    resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
+    engines: {node: '>=6'}
+
+  kuler@2.0.0:
+    resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==}
+
+  leven@3.1.0:
+    resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
+    engines: {node: '>=6'}
+
+  levn@0.4.1:
+    resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+    engines: {node: '>= 0.8.0'}
+
+  libphonenumber-js@1.11.4:
+    resolution: {integrity: sha512-F/R50HQuWWYcmU/esP5jrH5LiWYaN7DpN0a/99U8+mnGGtnx8kmRE+649dQh3v+CowXXZc8vpkf5AmYkO0AQ7Q==}
+
+  lines-and-columns@1.2.4:
+    resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+
+  loader-runner@4.3.0:
+    resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==}
+    engines: {node: '>=6.11.5'}
+
+  locate-path@5.0.0:
+    resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
+    engines: {node: '>=8'}
+
+  locate-path@6.0.0:
+    resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+    engines: {node: '>=10'}
+
+  lodash.includes@4.3.0:
+    resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
+
+  lodash.isboolean@3.0.3:
+    resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
+
+  lodash.isinteger@4.0.4:
+    resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
+
+  lodash.isnumber@3.0.3:
+    resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
+
+  lodash.isplainobject@4.0.6:
+    resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
+
+  lodash.isstring@4.0.1:
+    resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
+
+  lodash.memoize@4.1.2:
+    resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
+
+  lodash.merge@4.6.2:
+    resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+
+  lodash.once@4.1.1:
+    resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
+
+  lodash@4.17.21:
+    resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
+  log-symbols@4.1.0:
+    resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
+    engines: {node: '>=10'}
+
+  logform@2.6.1:
+    resolution: {integrity: sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==}
+    engines: {node: '>= 12.0.0'}
+
+  lru-cache@10.4.2:
+    resolution: {integrity: sha512-voV4dDrdVZVNz84n39LFKDaRzfwhdzJ7akpyXfTMxCgRUp07U3lcJUXRlhTKP17rgt09sUzLi5iCitpEAr+6ug==}
+    engines: {node: 14 || 16 || 18 || 20 || >=22}
+
+  lru-cache@5.1.1:
+    resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
+  magic-string@0.30.8:
+    resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==}
+    engines: {node: '>=12'}
+
+  make-dir@4.0.0:
+    resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
+    engines: {node: '>=10'}
+
+  make-error@1.3.6:
+    resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
+
+  makeerror@1.0.12:
+    resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==}
+
+  media-typer@0.3.0:
+    resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
+    engines: {node: '>= 0.6'}
+
+  memfs@3.5.3:
+    resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==}
+    engines: {node: '>= 4.0.0'}
+
+  merge-descriptors@1.0.1:
+    resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
+
+  merge-stream@2.0.0:
+    resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+
+  merge2@1.4.1:
+    resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+    engines: {node: '>= 8'}
+
+  methods@1.1.2:
+    resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
+    engines: {node: '>= 0.6'}
+
+  micromatch@4.0.7:
+    resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==}
+    engines: {node: '>=8.6'}
+
+  mime-db@1.52.0:
+    resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+    engines: {node: '>= 0.6'}
+
+  mime-types@2.1.35:
+    resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+    engines: {node: '>= 0.6'}
+
+  mime@1.6.0:
+    resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
+    engines: {node: '>=4'}
+    hasBin: true
+
+  mime@2.6.0:
+    resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==}
+    engines: {node: '>=4.0.0'}
+    hasBin: true
+
+  mimic-fn@2.1.0:
+    resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+    engines: {node: '>=6'}
+
+  minimatch@3.1.2:
+    resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+
+  minimatch@9.0.5:
+    resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
+    engines: {node: '>=16 || 14 >=14.17'}
+
+  minimist@1.2.8:
+    resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
+  minipass@7.1.2:
+    resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
+    engines: {node: '>=16 || 14 >=14.17'}
+
+  mkdirp@0.5.6:
+    resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
+    hasBin: true
+
+  moment@2.30.1:
+    resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
+
+  ms@2.0.0:
+    resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
+
+  ms@2.1.2:
+    resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+
+  ms@2.1.3:
+    resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+  multer@1.4.4-lts.1:
+    resolution: {integrity: sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==}
+    engines: {node: '>= 6.0.0'}
+
+  multer@1.4.5-lts.1:
+    resolution: {integrity: sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==}
+    engines: {node: '>= 6.0.0'}
+
+  mute-stream@0.0.8:
+    resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==}
+
+  mute-stream@1.0.0:
+    resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+
+  natural-compare@1.4.0:
+    resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+
+  negotiator@0.6.3:
+    resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
+    engines: {node: '>= 0.6'}
+
+  neo-async@2.6.2:
+    resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
+
+  nest-winston@1.9.7:
+    resolution: {integrity: sha512-pTTgImRgv7urojsDvaTlenAjyJNLj7ywamfjzrhWKhLhp80AKLYNwf103dVHeqZWe+nzp/vd9DGRs/UN/YadOQ==}
+    peerDependencies:
+      '@nestjs/common': ^5.0.0 || ^6.6.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0
+      winston: ^3.0.0
+
+  node-abort-controller@3.1.1:
+    resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==}
+
+  node-emoji@1.11.0:
+    resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==}
+
+  node-fetch@2.7.0:
+    resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
+    engines: {node: 4.x || >=6.0.0}
+    peerDependencies:
+      encoding: ^0.1.0
+    peerDependenciesMeta:
+      encoding:
+        optional: true
+
+  node-int64@0.4.0:
+    resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
+
+  node-releases@2.0.14:
+    resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
+
+  normalize-path@3.0.0:
+    resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+    engines: {node: '>=0.10.0'}
+
+  npm-run-path@4.0.1:
+    resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
+    engines: {node: '>=8'}
+
+  object-assign@4.1.1:
+    resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+    engines: {node: '>=0.10.0'}
+
+  object-hash@3.0.0:
+    resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
+    engines: {node: '>= 6'}
+
+  object-inspect@1.13.2:
+    resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==}
+    engines: {node: '>= 0.4'}
+
+  on-finished@2.4.1:
+    resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
+    engines: {node: '>= 0.8'}
+
+  on-headers@1.0.2:
+    resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
+    engines: {node: '>= 0.8'}
+
+  once@1.4.0:
+    resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+  one-time@1.0.0:
+    resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==}
+
+  onetime@5.1.2:
+    resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+    engines: {node: '>=6'}
+
+  opentype.js@0.7.3:
+    resolution: {integrity: sha512-Veui5vl2bLonFJ/SjX/WRWJT3SncgiZNnKUyahmXCc2sa1xXW15u3R/3TN5+JFiP7RsjK5ER4HA5eWaEmV9deA==}
+    hasBin: true
+
+  optionator@0.9.4:
+    resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
+    engines: {node: '>= 0.8.0'}
+
+  ora@5.4.1:
+    resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==}
+    engines: {node: '>=10'}
+
+  os-tmpdir@1.0.2:
+    resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==}
+    engines: {node: '>=0.10.0'}
+
+  p-limit@2.3.0:
+    resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+    engines: {node: '>=6'}
+
+  p-limit@3.1.0:
+    resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+    engines: {node: '>=10'}
+
+  p-locate@4.1.0:
+    resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
+    engines: {node: '>=8'}
+
+  p-locate@5.0.0:
+    resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+    engines: {node: '>=10'}
+
+  p-try@2.2.0:
+    resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+    engines: {node: '>=6'}
+
+  package-json-from-dist@1.0.0:
+    resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==}
+
+  parent-module@1.0.1:
+    resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+    engines: {node: '>=6'}
+
+  parse-json@5.2.0:
+    resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
+    engines: {node: '>=8'}
+
+  parseurl@1.3.3:
+    resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
+    engines: {node: '>= 0.8'}
+
+  passport-jwt@4.0.1:
+    resolution: {integrity: sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==}
+
+  passport-strategy@1.0.0:
+    resolution: {integrity: sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==}
+    engines: {node: '>= 0.4.0'}
+
+  passport@0.7.0:
+    resolution: {integrity: sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==}
+    engines: {node: '>= 0.4.0'}
+
+  path-exists@4.0.0:
+    resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+    engines: {node: '>=8'}
+
+  path-is-absolute@1.0.1:
+    resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+    engines: {node: '>=0.10.0'}
+
+  path-key@3.1.1:
+    resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+    engines: {node: '>=8'}
+
+  path-parse@1.0.7:
+    resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+  path-scurry@1.11.1:
+    resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
+    engines: {node: '>=16 || 14 >=14.18'}
+
+  path-to-regexp@0.1.7:
+    resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
+
+  path-to-regexp@3.2.0:
+    resolution: {integrity: sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==}
+
+  path-type@4.0.0:
+    resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+    engines: {node: '>=8'}
+
+  pause@0.0.1:
+    resolution: {integrity: sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==}
+
+  picocolors@1.0.1:
+    resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
+
+  picomatch@2.3.1:
+    resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+    engines: {node: '>=8.6'}
+
+  picomatch@4.0.1:
+    resolution: {integrity: sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==}
+    engines: {node: '>=12'}
+
+  pirates@4.0.6:
+    resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
+    engines: {node: '>= 6'}
+
+  pkg-dir@4.2.0:
+    resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
+    engines: {node: '>=8'}
+
+  pluralize@8.0.0:
+    resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
+    engines: {node: '>=4'}
+
+  prelude-ls@1.2.1:
+    resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+    engines: {node: '>= 0.8.0'}
+
+  prettier-linter-helpers@1.0.0:
+    resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==}
+    engines: {node: '>=6.0.0'}
+
+  prettier@3.3.2:
+    resolution: {integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==}
+    engines: {node: '>=14'}
+    hasBin: true
+
+  pretty-format@29.7.0:
+    resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+  prisma@5.16.1:
+    resolution: {integrity: sha512-Z1Uqodk44diztImxALgJJfNl2Uisl9xDRvqybMKEBYJLNKNhDfAHf+ZIJbZyYiBhLMbKU9cYGdDVG5IIXEnL2Q==}
+    engines: {node: '>=16.13'}
+    hasBin: true
+
+  process-nextick-args@2.0.1:
+    resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
+
+  prompts@2.4.2:
+    resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
+    engines: {node: '>= 6'}
+
+  proxy-addr@2.0.7:
+    resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
+    engines: {node: '>= 0.10'}
+
+  proxy-from-env@1.1.0:
+    resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+
+  punycode@2.3.1:
+    resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+    engines: {node: '>=6'}
+
+  pure-rand@6.1.0:
+    resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==}
+
+  qs@6.11.0:
+    resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
+    engines: {node: '>=0.6'}
+
+  qs@6.12.3:
+    resolution: {integrity: sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==}
+    engines: {node: '>=0.6'}
+
+  queue-microtask@1.2.3:
+    resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+  random-bytes@1.0.0:
+    resolution: {integrity: sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==}
+    engines: {node: '>= 0.8'}
+
+  randombytes@2.1.0:
+    resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
+
+  range-parser@1.2.1:
+    resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
+    engines: {node: '>= 0.6'}
+
+  raw-body@2.5.2:
+    resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==}
+    engines: {node: '>= 0.8'}
+
+  react-is@18.3.1:
+    resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+
+  readable-stream@2.3.8:
+    resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
+
+  readable-stream@3.6.2:
+    resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+    engines: {node: '>= 6'}
+
+  readdirp@3.6.0:
+    resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+    engines: {node: '>=8.10.0'}
+
+  reflect-metadata@0.2.2:
+    resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
+
+  repeat-string@1.6.1:
+    resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==}
+    engines: {node: '>=0.10'}
+
+  require-directory@2.1.1:
+    resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+    engines: {node: '>=0.10.0'}
+
+  require-from-string@2.0.2:
+    resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+    engines: {node: '>=0.10.0'}
+
+  resolve-cwd@3.0.0:
+    resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==}
+    engines: {node: '>=8'}
+
+  resolve-from@4.0.0:
+    resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+    engines: {node: '>=4'}
+
+  resolve-from@5.0.0:
+    resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
+    engines: {node: '>=8'}
+
+  resolve.exports@2.0.2:
+    resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==}
+    engines: {node: '>=10'}
+
+  resolve@1.22.8:
+    resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+    hasBin: true
+
+  restore-cursor@3.1.0:
+    resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
+    engines: {node: '>=8'}
+
+  reusify@1.0.4:
+    resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+    engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+  rimraf@3.0.2:
+    resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+    deprecated: Rimraf versions prior to v4 are no longer supported
+    hasBin: true
+
+  run-async@2.4.1:
+    resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==}
+    engines: {node: '>=0.12.0'}
+
+  run-async@3.0.0:
+    resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==}
+    engines: {node: '>=0.12.0'}
+
+  run-parallel@1.2.0:
+    resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+  run-script-webpack-plugin@0.2.0:
+    resolution: {integrity: sha512-SVNNq4jxzjfnaW+HkdTlyH1CWwCuSb/weYfic0D7Y/KnhY27YRYkzgybdzTDEPJlpQ73FDCRDbyBFwNsJMmwWQ==}
+    engines: {node: '>=14'}
+
+  rxjs@7.8.1:
+    resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
+
+  safe-buffer@5.1.2:
+    resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
+
+  safe-buffer@5.2.1:
+    resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
+  safe-stable-stringify@2.5.0:
+    resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
+    engines: {node: '>=10'}
+
+  safer-buffer@2.1.2:
+    resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
+  schema-utils@3.3.0:
+    resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==}
+    engines: {node: '>= 10.13.0'}
+
+  semver@6.3.1:
+    resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+    hasBin: true
+
+  semver@7.6.2:
+    resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==}
+    engines: {node: '>=10'}
+    hasBin: true
+
+  send@0.18.0:
+    resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
+    engines: {node: '>= 0.8.0'}
+
+  serialize-javascript@6.0.2:
+    resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
+
+  serve-static@1.15.0:
+    resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==}
+    engines: {node: '>= 0.8.0'}
+
+  set-function-length@1.2.2:
+    resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
+    engines: {node: '>= 0.4'}
+
+  setprototypeof@1.2.0:
+    resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+
+  shebang-command@2.0.0:
+    resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+    engines: {node: '>=8'}
+
+  shebang-regex@3.0.0:
+    resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+    engines: {node: '>=8'}
+
+  side-channel@1.0.6:
+    resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
+    engines: {node: '>= 0.4'}
+
+  signal-exit@3.0.7:
+    resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+
+  signal-exit@4.1.0:
+    resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+    engines: {node: '>=14'}
+
+  simple-swizzle@0.2.2:
+    resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
+
+  sisteransi@1.0.5:
+    resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
+
+  slash@3.0.0:
+    resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+    engines: {node: '>=8'}
+
+  source-map-support@0.5.13:
+    resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==}
+
+  source-map-support@0.5.21:
+    resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+
+  source-map@0.6.1:
+    resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+    engines: {node: '>=0.10.0'}
+
+  source-map@0.7.4:
+    resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
+    engines: {node: '>= 8'}
+
+  sprintf-js@1.0.3:
+    resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
+
+  ssf@0.11.2:
+    resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==}
+    engines: {node: '>=0.8'}
+
+  stack-trace@0.0.10:
+    resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==}
+
+  stack-utils@2.0.6:
+    resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
+    engines: {node: '>=10'}
+
+  statuses@2.0.1:
+    resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
+    engines: {node: '>= 0.8'}
+
+  streamsearch@1.1.0:
+    resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
+    engines: {node: '>=10.0.0'}
+
+  string-length@4.0.2:
+    resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==}
+    engines: {node: '>=10'}
+
+  string-width@4.2.3:
+    resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+    engines: {node: '>=8'}
+
+  string-width@5.1.2:
+    resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+    engines: {node: '>=12'}
+
+  string_decoder@1.1.1:
+    resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
+
+  string_decoder@1.3.0:
+    resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+
+  strip-ansi@6.0.1:
+    resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+    engines: {node: '>=8'}
+
+  strip-ansi@7.1.0:
+    resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+    engines: {node: '>=12'}
+
+  strip-bom@3.0.0:
+    resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
+    engines: {node: '>=4'}
+
+  strip-bom@4.0.0:
+    resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==}
+    engines: {node: '>=8'}
+
+  strip-final-newline@2.0.0:
+    resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
+    engines: {node: '>=6'}
+
+  strip-json-comments@3.1.1:
+    resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+    engines: {node: '>=8'}
+
+  superagent@9.0.2:
+    resolution: {integrity: sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==}
+    engines: {node: '>=14.18.0'}
+
+  supertest@7.0.0:
+    resolution: {integrity: sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==}
+    engines: {node: '>=14.18.0'}
+
+  supports-color@5.5.0:
+    resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+    engines: {node: '>=4'}
+
+  supports-color@7.2.0:
+    resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+    engines: {node: '>=8'}
+
+  supports-color@8.1.1:
+    resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
+    engines: {node: '>=10'}
+
+  supports-preserve-symlinks-flag@1.0.0:
+    resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+    engines: {node: '>= 0.4'}
+
+  svg-captcha@1.4.0:
+    resolution: {integrity: sha512-/fkkhavXPE57zRRCjNqAP3txRCSncpMx3NnNZL7iEoyAtYwUjPhJxW6FQTQPG5UPEmCrbFoXS10C3YdJlW7PDg==}
+    engines: {node: '>=4.x'}
+
+  swagger-ui-dist@5.17.14:
+    resolution: {integrity: sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==}
+
+  swagger-ui-express@5.0.1:
+    resolution: {integrity: sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==}
+    engines: {node: '>= v0.10.32'}
+    peerDependencies:
+      express: '>=4.0.0 || >=5.0.0-beta'
+
+  symbol-observable@4.0.0:
+    resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==}
+    engines: {node: '>=0.10'}
+
+  synckit@0.8.8:
+    resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+
+  tapable@2.2.1:
+    resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
+    engines: {node: '>=6'}
+
+  terser-webpack-plugin@5.3.10:
+    resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==}
+    engines: {node: '>= 10.13.0'}
+    peerDependencies:
+      '@swc/core': '*'
+      esbuild: '*'
+      uglify-js: '*'
+      webpack: ^5.1.0
+    peerDependenciesMeta:
+      '@swc/core':
+        optional: true
+      esbuild:
+        optional: true
+      uglify-js:
+        optional: true
+
+  terser@5.31.1:
+    resolution: {integrity: sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg==}
+    engines: {node: '>=10'}
+    hasBin: true
+
+  test-exclude@6.0.0:
+    resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==}
+    engines: {node: '>=8'}
+
+  text-hex@1.0.0:
+    resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==}
+
+  text-table@0.2.0:
+    resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+
+  through@2.3.8:
+    resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
+
+  tiny-inflate@1.0.3:
+    resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
+
+  tmp@0.0.33:
+    resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
+    engines: {node: '>=0.6.0'}
+
+  tmpl@1.0.5:
+    resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==}
+
+  to-fast-properties@2.0.0:
+    resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+    engines: {node: '>=4'}
+
+  to-regex-range@5.0.1:
+    resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+    engines: {node: '>=8.0'}
+
+  toidentifier@1.0.1:
+    resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
+    engines: {node: '>=0.6'}
+
+  tr46@0.0.3:
+    resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+
+  tree-kill@1.2.2:
+    resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+    hasBin: true
+
+  triple-beam@1.4.1:
+    resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==}
+    engines: {node: '>= 14.0.0'}
+
+  ts-api-utils@1.3.0:
+    resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
+    engines: {node: '>=16'}
+    peerDependencies:
+      typescript: '>=4.2.0'
+
+  ts-jest@29.2.0:
+    resolution: {integrity: sha512-eFmkE9MG0+oT6nqSOcUwL+2UUmK2IvhhUV8hFDsCHnc++v2WCCbQQZh5vvjsa8sgOY/g9T0325hmkEmi6rninA==}
+    engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0}
+    hasBin: true
+    peerDependencies:
+      '@babel/core': '>=7.0.0-beta.0 <8'
+      '@jest/transform': ^29.0.0
+      '@jest/types': ^29.0.0
+      babel-jest: ^29.0.0
+      esbuild: '*'
+      jest: ^29.0.0
+      typescript: '>=4.3 <6'
+    peerDependenciesMeta:
+      '@babel/core':
+        optional: true
+      '@jest/transform':
+        optional: true
+      '@jest/types':
+        optional: true
+      babel-jest:
+        optional: true
+      esbuild:
+        optional: true
+
+  ts-loader@9.5.1:
+    resolution: {integrity: sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==}
+    engines: {node: '>=12.0.0'}
+    peerDependencies:
+      typescript: '*'
+      webpack: ^5.0.0
+
+  ts-node@10.9.2:
+    resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
+    hasBin: true
+    peerDependencies:
+      '@swc/core': '>=1.2.50'
+      '@swc/wasm': '>=1.2.50'
+      '@types/node': '*'
+      typescript: '>=2.7'
+    peerDependenciesMeta:
+      '@swc/core':
+        optional: true
+      '@swc/wasm':
+        optional: true
+
+  tsconfig-paths-webpack-plugin@4.1.0:
+    resolution: {integrity: sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==}
+    engines: {node: '>=10.13.0'}
+
+  tsconfig-paths@4.2.0:
+    resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==}
+    engines: {node: '>=6'}
+
+  tslib@2.6.3:
+    resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==}
+
+  type-check@0.4.0:
+    resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+    engines: {node: '>= 0.8.0'}
+
+  type-detect@4.0.8:
+    resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
+    engines: {node: '>=4'}
+
+  type-fest@0.20.2:
+    resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
+    engines: {node: '>=10'}
+
+  type-fest@0.21.3:
+    resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
+    engines: {node: '>=10'}
+
+  type-is@1.6.18:
+    resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
+    engines: {node: '>= 0.6'}
+
+  typedarray@0.0.6:
+    resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==}
+
+  typescript@5.3.3:
+    resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
+    engines: {node: '>=14.17'}
+    hasBin: true
+
+  typescript@5.5.3:
+    resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==}
+    engines: {node: '>=14.17'}
+    hasBin: true
+
+  ua-parser-js@1.0.38:
+    resolution: {integrity: sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==}
+
+  uid-safe@2.1.5:
+    resolution: {integrity: sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==}
+    engines: {node: '>= 0.8'}
+
+  uid@2.0.2:
+    resolution: {integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==}
+    engines: {node: '>=8'}
+
+  undici-types@5.26.5:
+    resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+
+  universalify@2.0.1:
+    resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+    engines: {node: '>= 10.0.0'}
+
+  unpipe@1.0.0:
+    resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
+    engines: {node: '>= 0.8'}
+
+  update-browserslist-db@1.1.0:
+    resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==}
+    hasBin: true
+    peerDependencies:
+      browserslist: '>= 4.21.0'
+
+  uri-js@4.4.1:
+    resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+
+  util-deprecate@1.0.2:
+    resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+  utils-merge@1.0.1:
+    resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
+    engines: {node: '>= 0.4.0'}
+
+  uuid@10.0.0:
+    resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==}
+    hasBin: true
+
+  v8-compile-cache-lib@3.0.1:
+    resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
+
+  v8-to-istanbul@9.3.0:
+    resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==}
+    engines: {node: '>=10.12.0'}
+
+  validator@13.12.0:
+    resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==}
+    engines: {node: '>= 0.10'}
+
+  vary@1.1.2:
+    resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+    engines: {node: '>= 0.8'}
+
+  walker@1.0.8:
+    resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==}
+
+  watchpack@2.4.1:
+    resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==}
+    engines: {node: '>=10.13.0'}
+
+  wcwidth@1.0.1:
+    resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
+
+  webidl-conversions@3.0.1:
+    resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+
+  webpack-node-externals@3.0.0:
+    resolution: {integrity: sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==}
+    engines: {node: '>=6'}
+
+  webpack-sources@3.2.3:
+    resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
+    engines: {node: '>=10.13.0'}
+
+  webpack@5.92.1:
+    resolution: {integrity: sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==}
+    engines: {node: '>=10.13.0'}
+    hasBin: true
+    peerDependencies:
+      webpack-cli: '*'
+    peerDependenciesMeta:
+      webpack-cli:
+        optional: true
+
+  webpack@5.94.0:
+    resolution: {integrity: sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==}
+    engines: {node: '>=10.13.0'}
+    hasBin: true
+    peerDependencies:
+      webpack-cli: '*'
+    peerDependenciesMeta:
+      webpack-cli:
+        optional: true
+
+  whatwg-url@5.0.0:
+    resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+
+  which@2.0.2:
+    resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+    engines: {node: '>= 8'}
+    hasBin: true
+
+  winston-daily-rotate-file@5.0.0:
+    resolution: {integrity: sha512-JDjiXXkM5qvwY06733vf09I2wnMXpZEhxEVOSPenZMii+g7pcDcTBt2MRugnoi8BwVSuCT2jfRXBUy+n1Zz/Yw==}
+    engines: {node: '>=8'}
+    peerDependencies:
+      winston: ^3
+
+  winston-transport@4.7.1:
+    resolution: {integrity: sha512-wQCXXVgfv/wUPOfb2x0ruxzwkcZfxcktz6JIMUaPLmcNhO4bZTwA/WtDWK74xV3F2dKu8YadrFv0qhwYjVEwhA==}
+    engines: {node: '>= 12.0.0'}
+
+  winston@3.14.2:
+    resolution: {integrity: sha512-CO8cdpBB2yqzEf8v895L+GNKYJiEq8eKlHU38af3snQBQ+sdAIUepjMSguOIJC7ICbzm0ZI+Af2If4vIJrtmOg==}
+    engines: {node: '>= 12.0.0'}
+
+  wmf@1.0.2:
+    resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==}
+    engines: {node: '>=0.8'}
+
+  word-wrap@1.2.5:
+    resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
+    engines: {node: '>=0.10.0'}
+
+  word@0.3.0:
+    resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==}
+    engines: {node: '>=0.8'}
+
+  wrap-ansi@6.2.0:
+    resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
+    engines: {node: '>=8'}
+
+  wrap-ansi@7.0.0:
+    resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+    engines: {node: '>=10'}
+
+  wrap-ansi@8.1.0:
+    resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+    engines: {node: '>=12'}
+
+  wrappy@1.0.2:
+    resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+  write-file-atomic@4.0.2:
+    resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+
+  xlsx@0.18.5:
+    resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==}
+    engines: {node: '>=0.8'}
+    hasBin: true
+
+  xtend@4.0.2:
+    resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
+    engines: {node: '>=0.4'}
+
+  y18n@5.0.8:
+    resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+    engines: {node: '>=10'}
+
+  yallist@3.1.1:
+    resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
+  yargs-parser@21.1.1:
+    resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+    engines: {node: '>=12'}
+
+  yargs@17.7.2:
+    resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+    engines: {node: '>=12'}
+
+  yn@3.1.1:
+    resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
+    engines: {node: '>=6'}
+
+  yocto-queue@0.1.0:
+    resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+    engines: {node: '>=10'}
+
+snapshots:
+
+  '@ampproject/remapping@2.3.0':
+    dependencies:
+      '@jridgewell/gen-mapping': 0.3.5
+      '@jridgewell/trace-mapping': 0.3.25
+
+  '@angular-devkit/core@17.3.8(chokidar@3.6.0)':
+    dependencies:
+      ajv: 8.12.0
+      ajv-formats: 2.1.1(ajv@8.12.0)
+      jsonc-parser: 3.2.1
+      picomatch: 4.0.1
+      rxjs: 7.8.1
+      source-map: 0.7.4
+    optionalDependencies:
+      chokidar: 3.6.0
+
+  '@angular-devkit/schematics-cli@17.3.8(chokidar@3.6.0)':
+    dependencies:
+      '@angular-devkit/core': 17.3.8(chokidar@3.6.0)
+      '@angular-devkit/schematics': 17.3.8(chokidar@3.6.0)
+      ansi-colors: 4.1.3
+      inquirer: 9.2.15
+      symbol-observable: 4.0.0
+      yargs-parser: 21.1.1
+    transitivePeerDependencies:
+      - chokidar
+
+  '@angular-devkit/schematics@17.3.8(chokidar@3.6.0)':
+    dependencies:
+      '@angular-devkit/core': 17.3.8(chokidar@3.6.0)
+      jsonc-parser: 3.2.1
+      magic-string: 0.30.8
+      ora: 5.4.1
+      rxjs: 7.8.1
+    transitivePeerDependencies:
+      - chokidar
+
+  '@babel/code-frame@7.24.7':
+    dependencies:
+      '@babel/highlight': 7.24.7
+      picocolors: 1.0.1
+
+  '@babel/compat-data@7.24.7': {}
+
+  '@babel/core@7.24.7':
+    dependencies:
+      '@ampproject/remapping': 2.3.0
+      '@babel/code-frame': 7.24.7
+      '@babel/generator': 7.24.7
+      '@babel/helper-compilation-targets': 7.24.7
+      '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7)
+      '@babel/helpers': 7.24.7
+      '@babel/parser': 7.24.7
+      '@babel/template': 7.24.7
+      '@babel/traverse': 7.24.7
+      '@babel/types': 7.24.7
+      convert-source-map: 2.0.0
+      debug: 4.3.5
+      gensync: 1.0.0-beta.2
+      json5: 2.2.3
+      semver: 6.3.1
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/generator@7.24.7':
+    dependencies:
+      '@babel/types': 7.24.7
+      '@jridgewell/gen-mapping': 0.3.5
+      '@jridgewell/trace-mapping': 0.3.25
+      jsesc: 2.5.2
+
+  '@babel/helper-compilation-targets@7.24.7':
+    dependencies:
+      '@babel/compat-data': 7.24.7
+      '@babel/helper-validator-option': 7.24.7
+      browserslist: 4.23.1
+      lru-cache: 5.1.1
+      semver: 6.3.1
+
+  '@babel/helper-environment-visitor@7.24.7':
+    dependencies:
+      '@babel/types': 7.24.7
+
+  '@babel/helper-function-name@7.24.7':
+    dependencies:
+      '@babel/template': 7.24.7
+      '@babel/types': 7.24.7
+
+  '@babel/helper-hoist-variables@7.24.7':
+    dependencies:
+      '@babel/types': 7.24.7
+
+  '@babel/helper-module-imports@7.24.7':
+    dependencies:
+      '@babel/traverse': 7.24.7
+      '@babel/types': 7.24.7
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-module-transforms@7.24.7(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-environment-visitor': 7.24.7
+      '@babel/helper-module-imports': 7.24.7
+      '@babel/helper-simple-access': 7.24.7
+      '@babel/helper-split-export-declaration': 7.24.7
+      '@babel/helper-validator-identifier': 7.24.7
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-plugin-utils@7.24.7': {}
+
+  '@babel/helper-simple-access@7.24.7':
+    dependencies:
+      '@babel/traverse': 7.24.7
+      '@babel/types': 7.24.7
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-split-export-declaration@7.24.7':
+    dependencies:
+      '@babel/types': 7.24.7
+
+  '@babel/helper-string-parser@7.24.7': {}
+
+  '@babel/helper-validator-identifier@7.24.7': {}
+
+  '@babel/helper-validator-option@7.24.7': {}
+
+  '@babel/helpers@7.24.7':
+    dependencies:
+      '@babel/template': 7.24.7
+      '@babel/types': 7.24.7
+
+  '@babel/highlight@7.24.7':
+    dependencies:
+      '@babel/helper-validator-identifier': 7.24.7
+      chalk: 2.4.2
+      js-tokens: 4.0.0
+      picocolors: 1.0.1
+
+  '@babel/parser@7.24.7':
+    dependencies:
+      '@babel/types': 7.24.7
+
+  '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/plugin-syntax-typescript@7.24.7(@babel/core@7.24.7)':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+
+  '@babel/template@7.24.7':
+    dependencies:
+      '@babel/code-frame': 7.24.7
+      '@babel/parser': 7.24.7
+      '@babel/types': 7.24.7
+
+  '@babel/traverse@7.24.7':
+    dependencies:
+      '@babel/code-frame': 7.24.7
+      '@babel/generator': 7.24.7
+      '@babel/helper-environment-visitor': 7.24.7
+      '@babel/helper-function-name': 7.24.7
+      '@babel/helper-hoist-variables': 7.24.7
+      '@babel/helper-split-export-declaration': 7.24.7
+      '@babel/parser': 7.24.7
+      '@babel/types': 7.24.7
+      debug: 4.3.5
+      globals: 11.12.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/types@7.24.7':
+    dependencies:
+      '@babel/helper-string-parser': 7.24.7
+      '@babel/helper-validator-identifier': 7.24.7
+      to-fast-properties: 2.0.0
+
+  '@bcoe/v8-coverage@0.2.3': {}
+
+  '@colors/colors@1.5.0':
+    optional: true
+
+  '@colors/colors@1.6.0': {}
+
+  '@cspotcode/source-map-support@0.8.1':
+    dependencies:
+      '@jridgewell/trace-mapping': 0.3.9
+
+  '@dabh/diagnostics@2.0.3':
+    dependencies:
+      colorspace: 1.1.4
+      enabled: 2.0.0
+      kuler: 2.0.0
+
+  '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)':
+    dependencies:
+      eslint: 8.57.0
+      eslint-visitor-keys: 3.4.3
+
+  '@eslint-community/regexpp@4.11.0': {}
+
+  '@eslint/eslintrc@2.1.4':
+    dependencies:
+      ajv: 6.12.6
+      debug: 4.3.5
+      espree: 9.6.1
+      globals: 13.24.0
+      ignore: 5.3.1
+      import-fresh: 3.3.0
+      js-yaml: 4.1.0
+      minimatch: 3.1.2
+      strip-json-comments: 3.1.1
+    transitivePeerDependencies:
+      - supports-color
+
+  '@eslint/js@8.57.0': {}
+
+  '@humanwhocodes/config-array@0.11.14':
+    dependencies:
+      '@humanwhocodes/object-schema': 2.0.3
+      debug: 4.3.5
+      minimatch: 3.1.2
+    transitivePeerDependencies:
+      - supports-color
+
+  '@humanwhocodes/module-importer@1.0.1': {}
+
+  '@humanwhocodes/object-schema@2.0.3': {}
+
+  '@isaacs/cliui@8.0.2':
+    dependencies:
+      string-width: 5.1.2
+      string-width-cjs: string-width@4.2.3
+      strip-ansi: 7.1.0
+      strip-ansi-cjs: strip-ansi@6.0.1
+      wrap-ansi: 8.1.0
+      wrap-ansi-cjs: wrap-ansi@7.0.0
+
+  '@istanbuljs/load-nyc-config@1.1.0':
+    dependencies:
+      camelcase: 5.3.1
+      find-up: 4.1.0
+      get-package-type: 0.1.0
+      js-yaml: 3.14.1
+      resolve-from: 5.0.0
+
+  '@istanbuljs/schema@0.1.3': {}
+
+  '@jest/console@29.7.0':
+    dependencies:
+      '@jest/types': 29.6.3
+      '@types/node': 20.14.10
+      chalk: 4.1.2
+      jest-message-util: 29.7.0
+      jest-util: 29.7.0
+      slash: 3.0.0
+
+  '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))':
+    dependencies:
+      '@jest/console': 29.7.0
+      '@jest/reporters': 29.7.0
+      '@jest/test-result': 29.7.0
+      '@jest/transform': 29.7.0
+      '@jest/types': 29.6.3
+      '@types/node': 20.14.10
+      ansi-escapes: 4.3.2
+      chalk: 4.1.2
+      ci-info: 3.9.0
+      exit: 0.1.2
+      graceful-fs: 4.2.11
+      jest-changed-files: 29.7.0
+      jest-config: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))
+      jest-haste-map: 29.7.0
+      jest-message-util: 29.7.0
+      jest-regex-util: 29.6.3
+      jest-resolve: 29.7.0
+      jest-resolve-dependencies: 29.7.0
+      jest-runner: 29.7.0
+      jest-runtime: 29.7.0
+      jest-snapshot: 29.7.0
+      jest-util: 29.7.0
+      jest-validate: 29.7.0
+      jest-watcher: 29.7.0
+      micromatch: 4.0.7
+      pretty-format: 29.7.0
+      slash: 3.0.0
+      strip-ansi: 6.0.1
+    transitivePeerDependencies:
+      - babel-plugin-macros
+      - supports-color
+      - ts-node
+
+  '@jest/environment@29.7.0':
+    dependencies:
+      '@jest/fake-timers': 29.7.0
+      '@jest/types': 29.6.3
+      '@types/node': 20.14.10
+      jest-mock: 29.7.0
+
+  '@jest/expect-utils@29.7.0':
+    dependencies:
+      jest-get-type: 29.6.3
+
+  '@jest/expect@29.7.0':
+    dependencies:
+      expect: 29.7.0
+      jest-snapshot: 29.7.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@jest/fake-timers@29.7.0':
+    dependencies:
+      '@jest/types': 29.6.3
+      '@sinonjs/fake-timers': 10.3.0
+      '@types/node': 20.14.10
+      jest-message-util: 29.7.0
+      jest-mock: 29.7.0
+      jest-util: 29.7.0
+
+  '@jest/globals@29.7.0':
+    dependencies:
+      '@jest/environment': 29.7.0
+      '@jest/expect': 29.7.0
+      '@jest/types': 29.6.3
+      jest-mock: 29.7.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@jest/reporters@29.7.0':
+    dependencies:
+      '@bcoe/v8-coverage': 0.2.3
+      '@jest/console': 29.7.0
+      '@jest/test-result': 29.7.0
+      '@jest/transform': 29.7.0
+      '@jest/types': 29.6.3
+      '@jridgewell/trace-mapping': 0.3.25
+      '@types/node': 20.14.10
+      chalk: 4.1.2
+      collect-v8-coverage: 1.0.2
+      exit: 0.1.2
+      glob: 7.2.3
+      graceful-fs: 4.2.11
+      istanbul-lib-coverage: 3.2.2
+      istanbul-lib-instrument: 6.0.3
+      istanbul-lib-report: 3.0.1
+      istanbul-lib-source-maps: 4.0.1
+      istanbul-reports: 3.1.7
+      jest-message-util: 29.7.0
+      jest-util: 29.7.0
+      jest-worker: 29.7.0
+      slash: 3.0.0
+      string-length: 4.0.2
+      strip-ansi: 6.0.1
+      v8-to-istanbul: 9.3.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@jest/schemas@29.6.3':
+    dependencies:
+      '@sinclair/typebox': 0.27.8
+
+  '@jest/source-map@29.6.3':
+    dependencies:
+      '@jridgewell/trace-mapping': 0.3.25
+      callsites: 3.1.0
+      graceful-fs: 4.2.11
+
+  '@jest/test-result@29.7.0':
+    dependencies:
+      '@jest/console': 29.7.0
+      '@jest/types': 29.6.3
+      '@types/istanbul-lib-coverage': 2.0.6
+      collect-v8-coverage: 1.0.2
+
+  '@jest/test-sequencer@29.7.0':
+    dependencies:
+      '@jest/test-result': 29.7.0
+      graceful-fs: 4.2.11
+      jest-haste-map: 29.7.0
+      slash: 3.0.0
+
+  '@jest/transform@29.7.0':
+    dependencies:
+      '@babel/core': 7.24.7
+      '@jest/types': 29.6.3
+      '@jridgewell/trace-mapping': 0.3.25
+      babel-plugin-istanbul: 6.1.1
+      chalk: 4.1.2
+      convert-source-map: 2.0.0
+      fast-json-stable-stringify: 2.1.0
+      graceful-fs: 4.2.11
+      jest-haste-map: 29.7.0
+      jest-regex-util: 29.6.3
+      jest-util: 29.7.0
+      micromatch: 4.0.7
+      pirates: 4.0.6
+      slash: 3.0.0
+      write-file-atomic: 4.0.2
+    transitivePeerDependencies:
+      - supports-color
+
+  '@jest/types@29.6.3':
+    dependencies:
+      '@jest/schemas': 29.6.3
+      '@types/istanbul-lib-coverage': 2.0.6
+      '@types/istanbul-reports': 3.0.4
+      '@types/node': 20.14.10
+      '@types/yargs': 17.0.32
+      chalk: 4.1.2
+
+  '@jridgewell/gen-mapping@0.3.5':
+    dependencies:
+      '@jridgewell/set-array': 1.2.1
+      '@jridgewell/sourcemap-codec': 1.4.15
+      '@jridgewell/trace-mapping': 0.3.25
+
+  '@jridgewell/resolve-uri@3.1.2': {}
+
+  '@jridgewell/set-array@1.2.1': {}
+
+  '@jridgewell/source-map@0.3.6':
+    dependencies:
+      '@jridgewell/gen-mapping': 0.3.5
+      '@jridgewell/trace-mapping': 0.3.25
+
+  '@jridgewell/sourcemap-codec@1.4.15': {}
+
+  '@jridgewell/trace-mapping@0.3.25':
+    dependencies:
+      '@jridgewell/resolve-uri': 3.1.2
+      '@jridgewell/sourcemap-codec': 1.4.15
+
+  '@jridgewell/trace-mapping@0.3.9':
+    dependencies:
+      '@jridgewell/resolve-uri': 3.1.2
+      '@jridgewell/sourcemap-codec': 1.4.15
+
+  '@ljharb/through@2.3.13':
+    dependencies:
+      call-bind: 1.0.7
+
+  '@lukeed/csprng@1.1.0': {}
+
+  '@microsoft/tsdoc@0.15.0': {}
+
+  '@nestjs/axios@3.0.3(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(axios@1.7.4)(rxjs@7.8.1)':
+    dependencies:
+      '@nestjs/common': 10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      axios: 1.7.4
+      rxjs: 7.8.1
+
+  '@nestjs/cli@10.4.2':
+    dependencies:
+      '@angular-devkit/core': 17.3.8(chokidar@3.6.0)
+      '@angular-devkit/schematics': 17.3.8(chokidar@3.6.0)
+      '@angular-devkit/schematics-cli': 17.3.8(chokidar@3.6.0)
+      '@nestjs/schematics': 10.1.2(chokidar@3.6.0)(typescript@5.3.3)
+      chalk: 4.1.2
+      chokidar: 3.6.0
+      cli-table3: 0.6.5
+      commander: 4.1.1
+      fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.3.3)(webpack@5.92.1)
+      glob: 10.4.2
+      inquirer: 8.2.6
+      node-emoji: 1.11.0
+      ora: 5.4.1
+      tree-kill: 1.2.2
+      tsconfig-paths: 4.2.0
+      tsconfig-paths-webpack-plugin: 4.1.0
+      typescript: 5.3.3
+      webpack: 5.92.1
+      webpack-node-externals: 3.0.0
+    transitivePeerDependencies:
+      - esbuild
+      - uglify-js
+      - webpack-cli
+
+  '@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)':
+    dependencies:
+      iterare: 1.2.1
+      reflect-metadata: 0.2.2
+      rxjs: 7.8.1
+      tslib: 2.6.3
+      uid: 2.0.2
+    optionalDependencies:
+      class-transformer: 0.5.1
+      class-validator: 0.14.1
+
+  '@nestjs/core@10.3.10(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1)':
+    dependencies:
+      '@nestjs/common': 10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nuxtjs/opencollective': 0.3.2
+      fast-safe-stringify: 2.1.1
+      iterare: 1.2.1
+      path-to-regexp: 3.2.0
+      reflect-metadata: 0.2.2
+      rxjs: 7.8.1
+      tslib: 2.6.3
+      uid: 2.0.2
+    optionalDependencies:
+      '@nestjs/platform-express': 10.3.10(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10)
+    transitivePeerDependencies:
+      - encoding
+
+  '@nestjs/event-emitter@2.0.4(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10)':
+    dependencies:
+      '@nestjs/common': 10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nestjs/core': 10.3.10(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      eventemitter2: 6.4.9
+
+  '@nestjs/jwt@10.2.0(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))':
+    dependencies:
+      '@nestjs/common': 10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@types/jsonwebtoken': 9.0.5
+      jsonwebtoken: 9.0.2
+
+  '@nestjs/mapped-types@2.0.5(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)':
+    dependencies:
+      '@nestjs/common': 10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      reflect-metadata: 0.2.2
+    optionalDependencies:
+      class-transformer: 0.5.1
+      class-validator: 0.14.1
+
+  '@nestjs/passport@10.0.3(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(passport@0.7.0)':
+    dependencies:
+      '@nestjs/common': 10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      passport: 0.7.0
+
+  '@nestjs/platform-express@10.3.10(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10)':
+    dependencies:
+      '@nestjs/common': 10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nestjs/core': 10.3.10(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      body-parser: 1.20.2
+      cors: 2.8.5
+      express: 4.19.2
+      multer: 1.4.4-lts.1
+      tslib: 2.6.3
+    transitivePeerDependencies:
+      - supports-color
+
+  '@nestjs/schematics@10.1.2(chokidar@3.6.0)(typescript@5.3.3)':
+    dependencies:
+      '@angular-devkit/core': 17.3.8(chokidar@3.6.0)
+      '@angular-devkit/schematics': 17.3.8(chokidar@3.6.0)
+      comment-json: 4.2.3
+      jsonc-parser: 3.3.1
+      pluralize: 8.0.0
+      typescript: 5.3.3
+    transitivePeerDependencies:
+      - chokidar
+
+  '@nestjs/schematics@10.1.2(chokidar@3.6.0)(typescript@5.5.3)':
+    dependencies:
+      '@angular-devkit/core': 17.3.8(chokidar@3.6.0)
+      '@angular-devkit/schematics': 17.3.8(chokidar@3.6.0)
+      comment-json: 4.2.3
+      jsonc-parser: 3.3.1
+      pluralize: 8.0.0
+      typescript: 5.5.3
+    transitivePeerDependencies:
+      - chokidar
+
+  '@nestjs/swagger@7.4.0(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)':
+    dependencies:
+      '@microsoft/tsdoc': 0.15.0
+      '@nestjs/common': 10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nestjs/core': 10.3.10(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nestjs/mapped-types': 2.0.5(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)
+      js-yaml: 4.1.0
+      lodash: 4.17.21
+      path-to-regexp: 3.2.0
+      reflect-metadata: 0.2.2
+      swagger-ui-dist: 5.17.14
+    optionalDependencies:
+      class-transformer: 0.5.1
+      class-validator: 0.14.1
+
+  '@nestjs/testing@10.3.10(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10)(@nestjs/platform-express@10.3.10)':
+    dependencies:
+      '@nestjs/common': 10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nestjs/core': 10.3.10(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      tslib: 2.6.3
+    optionalDependencies:
+      '@nestjs/platform-express': 10.3.10(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10)
+
+  '@nodelib/fs.scandir@2.1.5':
+    dependencies:
+      '@nodelib/fs.stat': 2.0.5
+      run-parallel: 1.2.0
+
+  '@nodelib/fs.stat@2.0.5': {}
+
+  '@nodelib/fs.walk@1.2.8':
+    dependencies:
+      '@nodelib/fs.scandir': 2.1.5
+      fastq: 1.17.1
+
+  '@nuxtjs/opencollective@0.3.2':
+    dependencies:
+      chalk: 4.1.2
+      consola: 2.15.3
+      node-fetch: 2.7.0
+    transitivePeerDependencies:
+      - encoding
+
+  '@pkgjs/parseargs@0.11.0':
+    optional: true
+
+  '@pkgr/core@0.1.1': {}
+
+  '@prisma/client@5.16.1(prisma@5.16.1)':
+    optionalDependencies:
+      prisma: 5.16.1
+
+  '@prisma/debug@5.16.1': {}
+
+  '@prisma/engines-version@5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303': {}
+
+  '@prisma/engines@5.16.1':
+    dependencies:
+      '@prisma/debug': 5.16.1
+      '@prisma/engines-version': 5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303
+      '@prisma/fetch-engine': 5.16.1
+      '@prisma/get-platform': 5.16.1
+
+  '@prisma/fetch-engine@5.16.1':
+    dependencies:
+      '@prisma/debug': 5.16.1
+      '@prisma/engines-version': 5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303
+      '@prisma/get-platform': 5.16.1
+
+  '@prisma/get-platform@5.16.1':
+    dependencies:
+      '@prisma/debug': 5.16.1
+
+  '@sinclair/typebox@0.27.8': {}
+
+  '@sinonjs/commons@3.0.1':
+    dependencies:
+      type-detect: 4.0.8
+
+  '@sinonjs/fake-timers@10.3.0':
+    dependencies:
+      '@sinonjs/commons': 3.0.1
+
+  '@tsconfig/node10@1.0.11': {}
+
+  '@tsconfig/node12@1.0.11': {}
+
+  '@tsconfig/node14@1.0.3': {}
+
+  '@tsconfig/node16@1.0.4': {}
+
+  '@types/babel__core@7.20.5':
+    dependencies:
+      '@babel/parser': 7.24.7
+      '@babel/types': 7.24.7
+      '@types/babel__generator': 7.6.8
+      '@types/babel__template': 7.4.4
+      '@types/babel__traverse': 7.20.6
+
+  '@types/babel__generator@7.6.8':
+    dependencies:
+      '@babel/types': 7.24.7
+
+  '@types/babel__template@7.4.4':
+    dependencies:
+      '@babel/parser': 7.24.7
+      '@babel/types': 7.24.7
+
+  '@types/babel__traverse@7.20.6':
+    dependencies:
+      '@babel/types': 7.24.7
+
+  '@types/body-parser@1.19.5':
+    dependencies:
+      '@types/connect': 3.4.38
+      '@types/node': 20.14.10
+
+  '@types/connect@3.4.38':
+    dependencies:
+      '@types/node': 20.14.10
+
+  '@types/cookiejar@2.1.5': {}
+
+  '@types/eslint-scope@3.7.7':
+    dependencies:
+      '@types/eslint': 8.56.10
+      '@types/estree': 1.0.5
+
+  '@types/eslint@8.56.10':
+    dependencies:
+      '@types/estree': 1.0.5
+      '@types/json-schema': 7.0.15
+
+  '@types/estree@1.0.5': {}
+
+  '@types/express-serve-static-core@4.19.5':
+    dependencies:
+      '@types/node': 20.14.10
+      '@types/qs': 6.9.15
+      '@types/range-parser': 1.2.7
+      '@types/send': 0.17.4
+
+  '@types/express-session@1.18.0':
+    dependencies:
+      '@types/express': 4.17.21
+
+  '@types/express@4.17.21':
+    dependencies:
+      '@types/body-parser': 1.19.5
+      '@types/express-serve-static-core': 4.19.5
+      '@types/qs': 6.9.15
+      '@types/serve-static': 1.15.7
+
+  '@types/graceful-fs@4.1.9':
+    dependencies:
+      '@types/node': 20.14.10
+
+  '@types/http-errors@2.0.4': {}
+
+  '@types/istanbul-lib-coverage@2.0.6': {}
+
+  '@types/istanbul-lib-report@3.0.3':
+    dependencies:
+      '@types/istanbul-lib-coverage': 2.0.6
+
+  '@types/istanbul-reports@3.0.4':
+    dependencies:
+      '@types/istanbul-lib-report': 3.0.3
+
+  '@types/jest@29.5.12':
+    dependencies:
+      expect: 29.7.0
+      pretty-format: 29.7.0
+
+  '@types/json-schema@7.0.15': {}
+
+  '@types/jsonwebtoken@9.0.5':
+    dependencies:
+      '@types/node': 20.14.10
+
+  '@types/methods@1.1.4': {}
+
+  '@types/mime@1.3.5': {}
+
+  '@types/multer@1.4.11':
+    dependencies:
+      '@types/express': 4.17.21
+
+  '@types/node@20.14.10':
+    dependencies:
+      undici-types: 5.26.5
+
+  '@types/qs@6.9.15': {}
+
+  '@types/range-parser@1.2.7': {}
+
+  '@types/send@0.17.4':
+    dependencies:
+      '@types/mime': 1.3.5
+      '@types/node': 20.14.10
+
+  '@types/serve-static@1.15.7':
+    dependencies:
+      '@types/http-errors': 2.0.4
+      '@types/node': 20.14.10
+      '@types/send': 0.17.4
+
+  '@types/stack-utils@2.0.3': {}
+
+  '@types/superagent@8.1.7':
+    dependencies:
+      '@types/cookiejar': 2.1.5
+      '@types/methods': 1.1.4
+      '@types/node': 20.14.10
+
+  '@types/supertest@6.0.2':
+    dependencies:
+      '@types/methods': 1.1.4
+      '@types/superagent': 8.1.7
+
+  '@types/triple-beam@1.3.5': {}
+
+  '@types/validator@13.12.0': {}
+
+  '@types/yargs-parser@21.0.3': {}
+
+  '@types/yargs@17.0.32':
+    dependencies:
+      '@types/yargs-parser': 21.0.3
+
+  '@typescript-eslint/eslint-plugin@7.16.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)':
+    dependencies:
+      '@eslint-community/regexpp': 4.11.0
+      '@typescript-eslint/parser': 7.16.0(eslint@8.57.0)(typescript@5.5.3)
+      '@typescript-eslint/scope-manager': 7.16.0
+      '@typescript-eslint/type-utils': 7.16.0(eslint@8.57.0)(typescript@5.5.3)
+      '@typescript-eslint/utils': 7.16.0(eslint@8.57.0)(typescript@5.5.3)
+      '@typescript-eslint/visitor-keys': 7.16.0
+      eslint: 8.57.0
+      graphemer: 1.4.0
+      ignore: 5.3.1
+      natural-compare: 1.4.0
+      ts-api-utils: 1.3.0(typescript@5.5.3)
+    optionalDependencies:
+      typescript: 5.5.3
+    transitivePeerDependencies:
+      - supports-color
+
+  '@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3)':
+    dependencies:
+      '@typescript-eslint/scope-manager': 7.16.0
+      '@typescript-eslint/types': 7.16.0
+      '@typescript-eslint/typescript-estree': 7.16.0(typescript@5.5.3)
+      '@typescript-eslint/visitor-keys': 7.16.0
+      debug: 4.3.5
+      eslint: 8.57.0
+    optionalDependencies:
+      typescript: 5.5.3
+    transitivePeerDependencies:
+      - supports-color
+
+  '@typescript-eslint/scope-manager@7.16.0':
+    dependencies:
+      '@typescript-eslint/types': 7.16.0
+      '@typescript-eslint/visitor-keys': 7.16.0
+
+  '@typescript-eslint/type-utils@7.16.0(eslint@8.57.0)(typescript@5.5.3)':
+    dependencies:
+      '@typescript-eslint/typescript-estree': 7.16.0(typescript@5.5.3)
+      '@typescript-eslint/utils': 7.16.0(eslint@8.57.0)(typescript@5.5.3)
+      debug: 4.3.5
+      eslint: 8.57.0
+      ts-api-utils: 1.3.0(typescript@5.5.3)
+    optionalDependencies:
+      typescript: 5.5.3
+    transitivePeerDependencies:
+      - supports-color
+
+  '@typescript-eslint/types@7.16.0': {}
+
+  '@typescript-eslint/typescript-estree@7.16.0(typescript@5.5.3)':
+    dependencies:
+      '@typescript-eslint/types': 7.16.0
+      '@typescript-eslint/visitor-keys': 7.16.0
+      debug: 4.3.5
+      globby: 11.1.0
+      is-glob: 4.0.3
+      minimatch: 9.0.5
+      semver: 7.6.2
+      ts-api-utils: 1.3.0(typescript@5.5.3)
+    optionalDependencies:
+      typescript: 5.5.3
+    transitivePeerDependencies:
+      - supports-color
+
+  '@typescript-eslint/utils@7.16.0(eslint@8.57.0)(typescript@5.5.3)':
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
+      '@typescript-eslint/scope-manager': 7.16.0
+      '@typescript-eslint/types': 7.16.0
+      '@typescript-eslint/typescript-estree': 7.16.0(typescript@5.5.3)
+      eslint: 8.57.0
+    transitivePeerDependencies:
+      - supports-color
+      - typescript
+
+  '@typescript-eslint/visitor-keys@7.16.0':
+    dependencies:
+      '@typescript-eslint/types': 7.16.0
+      eslint-visitor-keys: 3.4.3
+
+  '@ungap/structured-clone@1.2.0': {}
+
+  '@webassemblyjs/ast@1.12.1':
+    dependencies:
+      '@webassemblyjs/helper-numbers': 1.11.6
+      '@webassemblyjs/helper-wasm-bytecode': 1.11.6
+
+  '@webassemblyjs/floating-point-hex-parser@1.11.6': {}
+
+  '@webassemblyjs/helper-api-error@1.11.6': {}
+
+  '@webassemblyjs/helper-buffer@1.12.1': {}
+
+  '@webassemblyjs/helper-numbers@1.11.6':
+    dependencies:
+      '@webassemblyjs/floating-point-hex-parser': 1.11.6
+      '@webassemblyjs/helper-api-error': 1.11.6
+      '@xtuc/long': 4.2.2
+
+  '@webassemblyjs/helper-wasm-bytecode@1.11.6': {}
+
+  '@webassemblyjs/helper-wasm-section@1.12.1':
+    dependencies:
+      '@webassemblyjs/ast': 1.12.1
+      '@webassemblyjs/helper-buffer': 1.12.1
+      '@webassemblyjs/helper-wasm-bytecode': 1.11.6
+      '@webassemblyjs/wasm-gen': 1.12.1
+
+  '@webassemblyjs/ieee754@1.11.6':
+    dependencies:
+      '@xtuc/ieee754': 1.2.0
+
+  '@webassemblyjs/leb128@1.11.6':
+    dependencies:
+      '@xtuc/long': 4.2.2
+
+  '@webassemblyjs/utf8@1.11.6': {}
+
+  '@webassemblyjs/wasm-edit@1.12.1':
+    dependencies:
+      '@webassemblyjs/ast': 1.12.1
+      '@webassemblyjs/helper-buffer': 1.12.1
+      '@webassemblyjs/helper-wasm-bytecode': 1.11.6
+      '@webassemblyjs/helper-wasm-section': 1.12.1
+      '@webassemblyjs/wasm-gen': 1.12.1
+      '@webassemblyjs/wasm-opt': 1.12.1
+      '@webassemblyjs/wasm-parser': 1.12.1
+      '@webassemblyjs/wast-printer': 1.12.1
+
+  '@webassemblyjs/wasm-gen@1.12.1':
+    dependencies:
+      '@webassemblyjs/ast': 1.12.1
+      '@webassemblyjs/helper-wasm-bytecode': 1.11.6
+      '@webassemblyjs/ieee754': 1.11.6
+      '@webassemblyjs/leb128': 1.11.6
+      '@webassemblyjs/utf8': 1.11.6
+
+  '@webassemblyjs/wasm-opt@1.12.1':
+    dependencies:
+      '@webassemblyjs/ast': 1.12.1
+      '@webassemblyjs/helper-buffer': 1.12.1
+      '@webassemblyjs/wasm-gen': 1.12.1
+      '@webassemblyjs/wasm-parser': 1.12.1
+
+  '@webassemblyjs/wasm-parser@1.12.1':
+    dependencies:
+      '@webassemblyjs/ast': 1.12.1
+      '@webassemblyjs/helper-api-error': 1.11.6
+      '@webassemblyjs/helper-wasm-bytecode': 1.11.6
+      '@webassemblyjs/ieee754': 1.11.6
+      '@webassemblyjs/leb128': 1.11.6
+      '@webassemblyjs/utf8': 1.11.6
+
+  '@webassemblyjs/wast-printer@1.12.1':
+    dependencies:
+      '@webassemblyjs/ast': 1.12.1
+      '@xtuc/long': 4.2.2
+
+  '@xtuc/ieee754@1.2.0': {}
+
+  '@xtuc/long@4.2.2': {}
+
+  accepts@1.3.8:
+    dependencies:
+      mime-types: 2.1.35
+      negotiator: 0.6.3
+
+  acorn-import-attributes@1.9.5(acorn@8.12.1):
+    dependencies:
+      acorn: 8.12.1
+
+  acorn-jsx@5.3.2(acorn@8.12.1):
+    dependencies:
+      acorn: 8.12.1
+
+  acorn-walk@8.3.3:
+    dependencies:
+      acorn: 8.12.1
+
+  acorn@8.12.1: {}
+
+  adler-32@1.3.1: {}
+
+  ajv-formats@2.1.1(ajv@8.12.0):
+    optionalDependencies:
+      ajv: 8.12.0
+
+  ajv-keywords@3.5.2(ajv@6.12.6):
+    dependencies:
+      ajv: 6.12.6
+
+  ajv@6.12.6:
+    dependencies:
+      fast-deep-equal: 3.1.3
+      fast-json-stable-stringify: 2.1.0
+      json-schema-traverse: 0.4.1
+      uri-js: 4.4.1
+
+  ajv@8.12.0:
+    dependencies:
+      fast-deep-equal: 3.1.3
+      json-schema-traverse: 1.0.0
+      require-from-string: 2.0.2
+      uri-js: 4.4.1
+
+  ansi-colors@4.1.3: {}
+
+  ansi-escapes@4.3.2:
+    dependencies:
+      type-fest: 0.21.3
+
+  ansi-regex@5.0.1: {}
+
+  ansi-regex@6.0.1: {}
+
+  ansi-styles@3.2.1:
+    dependencies:
+      color-convert: 1.9.3
+
+  ansi-styles@4.3.0:
+    dependencies:
+      color-convert: 2.0.1
+
+  ansi-styles@5.2.0: {}
+
+  ansi-styles@6.2.1: {}
+
+  anymatch@3.1.3:
+    dependencies:
+      normalize-path: 3.0.0
+      picomatch: 2.3.1
+
+  append-field@1.0.0: {}
+
+  arg@4.1.3: {}
+
+  argparse@1.0.10:
+    dependencies:
+      sprintf-js: 1.0.3
+
+  argparse@2.0.1: {}
+
+  array-flatten@1.1.1: {}
+
+  array-timsort@1.0.3: {}
+
+  array-union@2.1.0: {}
+
+  asap@2.0.6: {}
+
+  async@3.2.6: {}
+
+  asynckit@0.4.0: {}
+
+  axios@1.7.4:
+    dependencies:
+      follow-redirects: 1.15.6
+      form-data: 4.0.0
+      proxy-from-env: 1.1.0
+    transitivePeerDependencies:
+      - debug
+
+  babel-jest@29.7.0(@babel/core@7.24.7):
+    dependencies:
+      '@babel/core': 7.24.7
+      '@jest/transform': 29.7.0
+      '@types/babel__core': 7.20.5
+      babel-plugin-istanbul: 6.1.1
+      babel-preset-jest: 29.6.3(@babel/core@7.24.7)
+      chalk: 4.1.2
+      graceful-fs: 4.2.11
+      slash: 3.0.0
+    transitivePeerDependencies:
+      - supports-color
+
+  babel-plugin-istanbul@6.1.1:
+    dependencies:
+      '@babel/helper-plugin-utils': 7.24.7
+      '@istanbuljs/load-nyc-config': 1.1.0
+      '@istanbuljs/schema': 0.1.3
+      istanbul-lib-instrument: 5.2.1
+      test-exclude: 6.0.0
+    transitivePeerDependencies:
+      - supports-color
+
+  babel-plugin-jest-hoist@29.6.3:
+    dependencies:
+      '@babel/template': 7.24.7
+      '@babel/types': 7.24.7
+      '@types/babel__core': 7.20.5
+      '@types/babel__traverse': 7.20.6
+
+  babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.7):
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.7)
+      '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.7)
+      '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.7)
+      '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.7)
+      '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.7)
+      '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.7)
+      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.7)
+      '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.7)
+      '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.7)
+      '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.7)
+      '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.7)
+      '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.7)
+
+  babel-preset-jest@29.6.3(@babel/core@7.24.7):
+    dependencies:
+      '@babel/core': 7.24.7
+      babel-plugin-jest-hoist: 29.6.3
+      babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.7)
+
+  balanced-match@1.0.2: {}
+
+  base64-js@1.5.1: {}
+
+  bcryptjs@3.0.2: {}
+
+  binary-extensions@2.3.0: {}
+
+  bl@4.1.0:
+    dependencies:
+      buffer: 5.7.1
+      inherits: 2.0.4
+      readable-stream: 3.6.2
+
+  body-parser@1.20.2:
+    dependencies:
+      bytes: 3.1.2
+      content-type: 1.0.5
+      debug: 2.6.9
+      depd: 2.0.0
+      destroy: 1.2.0
+      http-errors: 2.0.0
+      iconv-lite: 0.4.24
+      on-finished: 2.4.1
+      qs: 6.11.0
+      raw-body: 2.5.2
+      type-is: 1.6.18
+      unpipe: 1.0.0
+    transitivePeerDependencies:
+      - supports-color
+
+  brace-expansion@1.1.11:
+    dependencies:
+      balanced-match: 1.0.2
+      concat-map: 0.0.1
+
+  brace-expansion@2.0.1:
+    dependencies:
+      balanced-match: 1.0.2
+
+  braces@3.0.3:
+    dependencies:
+      fill-range: 7.1.1
+
+  browserslist@4.23.1:
+    dependencies:
+      caniuse-lite: 1.0.30001640
+      electron-to-chromium: 1.4.819
+      node-releases: 2.0.14
+      update-browserslist-db: 1.1.0(browserslist@4.23.1)
+
+  bs-logger@0.2.6:
+    dependencies:
+      fast-json-stable-stringify: 2.1.0
+
+  bser@2.1.1:
+    dependencies:
+      node-int64: 0.4.0
+
+  buffer-equal-constant-time@1.0.1: {}
+
+  buffer-from@1.1.2: {}
+
+  buffer@5.7.1:
+    dependencies:
+      base64-js: 1.5.1
+      ieee754: 1.2.1
+
+  busboy@1.6.0:
+    dependencies:
+      streamsearch: 1.1.0
+
+  bytes@3.1.2: {}
+
+  call-bind@1.0.7:
+    dependencies:
+      es-define-property: 1.0.0
+      es-errors: 1.3.0
+      function-bind: 1.1.2
+      get-intrinsic: 1.2.4
+      set-function-length: 1.2.2
+
+  callsites@3.1.0: {}
+
+  camelcase@5.3.1: {}
+
+  camelcase@6.3.0: {}
+
+  caniuse-lite@1.0.30001640: {}
+
+  cfb@1.2.2:
+    dependencies:
+      adler-32: 1.3.1
+      crc-32: 1.2.2
+
+  chalk@2.4.2:
+    dependencies:
+      ansi-styles: 3.2.1
+      escape-string-regexp: 1.0.5
+      supports-color: 5.5.0
+
+  chalk@4.1.2:
+    dependencies:
+      ansi-styles: 4.3.0
+      supports-color: 7.2.0
+
+  chalk@5.3.0: {}
+
+  char-regex@1.0.2: {}
+
+  chardet@0.7.0: {}
+
+  chokidar@3.6.0:
+    dependencies:
+      anymatch: 3.1.3
+      braces: 3.0.3
+      glob-parent: 5.1.2
+      is-binary-path: 2.1.0
+      is-glob: 4.0.3
+      normalize-path: 3.0.0
+      readdirp: 3.6.0
+    optionalDependencies:
+      fsevents: 2.3.3
+
+  chrome-trace-event@1.0.4: {}
+
+  ci-info@3.9.0: {}
+
+  cjs-module-lexer@1.3.1: {}
+
+  class-transformer@0.5.1: {}
+
+  class-validator@0.14.1:
+    dependencies:
+      '@types/validator': 13.12.0
+      libphonenumber-js: 1.11.4
+      validator: 13.12.0
+
+  cli-cursor@3.1.0:
+    dependencies:
+      restore-cursor: 3.1.0
+
+  cli-spinners@2.9.2: {}
+
+  cli-table3@0.6.5:
+    dependencies:
+      string-width: 4.2.3
+    optionalDependencies:
+      '@colors/colors': 1.5.0
+
+  cli-width@3.0.0: {}
+
+  cli-width@4.1.0: {}
+
+  cliui@8.0.1:
+    dependencies:
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+      wrap-ansi: 7.0.0
+
+  clone@1.0.4: {}
+
+  co@4.6.0: {}
+
+  codepage@1.15.0: {}
+
+  collect-v8-coverage@1.0.2: {}
+
+  color-convert@1.9.3:
+    dependencies:
+      color-name: 1.1.3
+
+  color-convert@2.0.1:
+    dependencies:
+      color-name: 1.1.4
+
+  color-name@1.1.3: {}
+
+  color-name@1.1.4: {}
+
+  color-string@1.9.1:
+    dependencies:
+      color-name: 1.1.4
+      simple-swizzle: 0.2.2
+
+  color@3.2.1:
+    dependencies:
+      color-convert: 1.9.3
+      color-string: 1.9.1
+
+  colorspace@1.1.4:
+    dependencies:
+      color: 3.2.1
+      text-hex: 1.0.0
+
+  combined-stream@1.0.8:
+    dependencies:
+      delayed-stream: 1.0.0
+
+  commander@2.20.3: {}
+
+  commander@4.1.1: {}
+
+  comment-json@4.2.3:
+    dependencies:
+      array-timsort: 1.0.3
+      core-util-is: 1.0.3
+      esprima: 4.0.1
+      has-own-prop: 2.0.0
+      repeat-string: 1.6.1
+
+  component-emitter@1.3.1: {}
+
+  concat-map@0.0.1: {}
+
+  concat-stream@1.6.2:
+    dependencies:
+      buffer-from: 1.1.2
+      inherits: 2.0.4
+      readable-stream: 2.3.8
+      typedarray: 0.0.6
+
+  consola@2.15.3: {}
+
+  content-disposition@0.5.4:
+    dependencies:
+      safe-buffer: 5.2.1
+
+  content-type@1.0.5: {}
+
+  convert-source-map@2.0.0: {}
+
+  cookie-signature@1.0.6: {}
+
+  cookie-signature@1.0.7: {}
+
+  cookie@0.6.0: {}
+
+  cookiejar@2.1.4: {}
+
+  core-util-is@1.0.3: {}
+
+  cors@2.8.5:
+    dependencies:
+      object-assign: 4.1.1
+      vary: 1.1.2
+
+  cosmiconfig@8.3.6(typescript@5.3.3):
+    dependencies:
+      import-fresh: 3.3.0
+      js-yaml: 4.1.0
+      parse-json: 5.2.0
+      path-type: 4.0.0
+    optionalDependencies:
+      typescript: 5.3.3
+
+  crc-32@1.2.2: {}
+
+  create-jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)):
+    dependencies:
+      '@jest/types': 29.6.3
+      chalk: 4.1.2
+      exit: 0.1.2
+      graceful-fs: 4.2.11
+      jest-config: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))
+      jest-util: 29.7.0
+      prompts: 2.4.2
+    transitivePeerDependencies:
+      - '@types/node'
+      - babel-plugin-macros
+      - supports-color
+      - ts-node
+
+  create-require@1.1.1: {}
+
+  cross-spawn@7.0.3:
+    dependencies:
+      path-key: 3.1.1
+      shebang-command: 2.0.0
+      which: 2.0.2
+
+  dayjs@1.11.11: {}
+
+  debug@2.6.9:
+    dependencies:
+      ms: 2.0.0
+
+  debug@4.3.5:
+    dependencies:
+      ms: 2.1.2
+
+  dedent@1.5.3: {}
+
+  deep-is@0.1.4: {}
+
+  deepmerge@4.3.1: {}
+
+  defaults@1.0.4:
+    dependencies:
+      clone: 1.0.4
+
+  define-data-property@1.1.4:
+    dependencies:
+      es-define-property: 1.0.0
+      es-errors: 1.3.0
+      gopd: 1.0.1
+
+  delayed-stream@1.0.0: {}
+
+  depd@2.0.0: {}
+
+  destroy@1.2.0: {}
+
+  detect-newline@3.1.0: {}
+
+  dezalgo@1.0.4:
+    dependencies:
+      asap: 2.0.6
+      wrappy: 1.0.2
+
+  diff-sequences@29.6.3: {}
+
+  diff@4.0.2: {}
+
+  dir-glob@3.0.1:
+    dependencies:
+      path-type: 4.0.0
+
+  doctrine@3.0.0:
+    dependencies:
+      esutils: 2.0.3
+
+  eastasianwidth@0.2.0: {}
+
+  ecdsa-sig-formatter@1.0.11:
+    dependencies:
+      safe-buffer: 5.2.1
+
+  ee-first@1.1.1: {}
+
+  electron-to-chromium@1.4.819: {}
+
+  emittery@0.13.1: {}
+
+  emoji-regex@8.0.0: {}
+
+  emoji-regex@9.2.2: {}
+
+  enabled@2.0.0: {}
+
+  encodeurl@1.0.2: {}
+
+  enhanced-resolve@5.17.0:
+    dependencies:
+      graceful-fs: 4.2.11
+      tapable: 2.2.1
+
+  enhanced-resolve@5.17.1:
+    dependencies:
+      graceful-fs: 4.2.11
+      tapable: 2.2.1
+
+  error-ex@1.3.2:
+    dependencies:
+      is-arrayish: 0.2.1
+
+  es-define-property@1.0.0:
+    dependencies:
+      get-intrinsic: 1.2.4
+
+  es-errors@1.3.0: {}
+
+  es-module-lexer@1.5.4: {}
+
+  escalade@3.1.2: {}
+
+  escape-html@1.0.3: {}
+
+  escape-string-regexp@1.0.5: {}
+
+  escape-string-regexp@2.0.0: {}
+
+  escape-string-regexp@4.0.0: {}
+
+  eslint-config-prettier@9.1.0(eslint@8.57.0):
+    dependencies:
+      eslint: 8.57.0
+
+  eslint-plugin-prettier@5.1.3(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.2):
+    dependencies:
+      eslint: 8.57.0
+      prettier: 3.3.2
+      prettier-linter-helpers: 1.0.0
+      synckit: 0.8.8
+    optionalDependencies:
+      '@types/eslint': 8.56.10
+      eslint-config-prettier: 9.1.0(eslint@8.57.0)
+
+  eslint-plugin-simple-import-sort@12.1.1(eslint@8.57.0):
+    dependencies:
+      eslint: 8.57.0
+
+  eslint-scope@5.1.1:
+    dependencies:
+      esrecurse: 4.3.0
+      estraverse: 4.3.0
+
+  eslint-scope@7.2.2:
+    dependencies:
+      esrecurse: 4.3.0
+      estraverse: 5.3.0
+
+  eslint-visitor-keys@3.4.3: {}
+
+  eslint@8.57.0:
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
+      '@eslint-community/regexpp': 4.11.0
+      '@eslint/eslintrc': 2.1.4
+      '@eslint/js': 8.57.0
+      '@humanwhocodes/config-array': 0.11.14
+      '@humanwhocodes/module-importer': 1.0.1
+      '@nodelib/fs.walk': 1.2.8
+      '@ungap/structured-clone': 1.2.0
+      ajv: 6.12.6
+      chalk: 4.1.2
+      cross-spawn: 7.0.3
+      debug: 4.3.5
+      doctrine: 3.0.0
+      escape-string-regexp: 4.0.0
+      eslint-scope: 7.2.2
+      eslint-visitor-keys: 3.4.3
+      espree: 9.6.1
+      esquery: 1.6.0
+      esutils: 2.0.3
+      fast-deep-equal: 3.1.3
+      file-entry-cache: 6.0.1
+      find-up: 5.0.0
+      glob-parent: 6.0.2
+      globals: 13.24.0
+      graphemer: 1.4.0
+      ignore: 5.3.1
+      imurmurhash: 0.1.4
+      is-glob: 4.0.3
+      is-path-inside: 3.0.3
+      js-yaml: 4.1.0
+      json-stable-stringify-without-jsonify: 1.0.1
+      levn: 0.4.1
+      lodash.merge: 4.6.2
+      minimatch: 3.1.2
+      natural-compare: 1.4.0
+      optionator: 0.9.4
+      strip-ansi: 6.0.1
+      text-table: 0.2.0
+    transitivePeerDependencies:
+      - supports-color
+
+  espree@9.6.1:
+    dependencies:
+      acorn: 8.12.1
+      acorn-jsx: 5.3.2(acorn@8.12.1)
+      eslint-visitor-keys: 3.4.3
+
+  esprima@4.0.1: {}
+
+  esquery@1.6.0:
+    dependencies:
+      estraverse: 5.3.0
+
+  esrecurse@4.3.0:
+    dependencies:
+      estraverse: 5.3.0
+
+  estraverse@4.3.0: {}
+
+  estraverse@5.3.0: {}
+
+  esutils@2.0.3: {}
+
+  etag@1.8.1: {}
+
+  eventemitter2@6.4.9: {}
+
+  events@3.3.0: {}
+
+  execa@5.1.1:
+    dependencies:
+      cross-spawn: 7.0.3
+      get-stream: 6.0.1
+      human-signals: 2.1.0
+      is-stream: 2.0.1
+      merge-stream: 2.0.0
+      npm-run-path: 4.0.1
+      onetime: 5.1.2
+      signal-exit: 3.0.7
+      strip-final-newline: 2.0.0
+
+  exit@0.1.2: {}
+
+  expect@29.7.0:
+    dependencies:
+      '@jest/expect-utils': 29.7.0
+      jest-get-type: 29.6.3
+      jest-matcher-utils: 29.7.0
+      jest-message-util: 29.7.0
+      jest-util: 29.7.0
+
+  express-session@1.18.0:
+    dependencies:
+      cookie: 0.6.0
+      cookie-signature: 1.0.7
+      debug: 2.6.9
+      depd: 2.0.0
+      on-headers: 1.0.2
+      parseurl: 1.3.3
+      safe-buffer: 5.2.1
+      uid-safe: 2.1.5
+    transitivePeerDependencies:
+      - supports-color
+
+  express@4.19.2:
+    dependencies:
+      accepts: 1.3.8
+      array-flatten: 1.1.1
+      body-parser: 1.20.2
+      content-disposition: 0.5.4
+      content-type: 1.0.5
+      cookie: 0.6.0
+      cookie-signature: 1.0.6
+      debug: 2.6.9
+      depd: 2.0.0
+      encodeurl: 1.0.2
+      escape-html: 1.0.3
+      etag: 1.8.1
+      finalhandler: 1.2.0
+      fresh: 0.5.2
+      http-errors: 2.0.0
+      merge-descriptors: 1.0.1
+      methods: 1.1.2
+      on-finished: 2.4.1
+      parseurl: 1.3.3
+      path-to-regexp: 0.1.7
+      proxy-addr: 2.0.7
+      qs: 6.11.0
+      range-parser: 1.2.1
+      safe-buffer: 5.2.1
+      send: 0.18.0
+      serve-static: 1.15.0
+      setprototypeof: 1.2.0
+      statuses: 2.0.1
+      type-is: 1.6.18
+      utils-merge: 1.0.1
+      vary: 1.1.2
+    transitivePeerDependencies:
+      - supports-color
+
+  external-editor@3.1.0:
+    dependencies:
+      chardet: 0.7.0
+      iconv-lite: 0.4.24
+      tmp: 0.0.33
+
+  fast-deep-equal@3.1.3: {}
+
+  fast-diff@1.3.0: {}
+
+  fast-glob@3.3.2:
+    dependencies:
+      '@nodelib/fs.stat': 2.0.5
+      '@nodelib/fs.walk': 1.2.8
+      glob-parent: 5.1.2
+      merge2: 1.4.1
+      micromatch: 4.0.7
+
+  fast-json-stable-stringify@2.1.0: {}
+
+  fast-levenshtein@2.0.6: {}
+
+  fast-safe-stringify@2.1.1: {}
+
+  fastq@1.17.1:
+    dependencies:
+      reusify: 1.0.4
+
+  fb-watchman@2.0.2:
+    dependencies:
+      bser: 2.1.1
+
+  fecha@4.2.3: {}
+
+  figures@3.2.0:
+    dependencies:
+      escape-string-regexp: 1.0.5
+
+  file-entry-cache@6.0.1:
+    dependencies:
+      flat-cache: 3.2.0
+
+  file-stream-rotator@0.6.1:
+    dependencies:
+      moment: 2.30.1
+
+  fill-range@7.1.1:
+    dependencies:
+      to-regex-range: 5.0.1
+
+  finalhandler@1.2.0:
+    dependencies:
+      debug: 2.6.9
+      encodeurl: 1.0.2
+      escape-html: 1.0.3
+      on-finished: 2.4.1
+      parseurl: 1.3.3
+      statuses: 2.0.1
+      unpipe: 1.0.0
+    transitivePeerDependencies:
+      - supports-color
+
+  find-up@4.1.0:
+    dependencies:
+      locate-path: 5.0.0
+      path-exists: 4.0.0
+
+  find-up@5.0.0:
+    dependencies:
+      locate-path: 6.0.0
+      path-exists: 4.0.0
+
+  flat-cache@3.2.0:
+    dependencies:
+      flatted: 3.3.1
+      keyv: 4.5.4
+      rimraf: 3.0.2
+
+  flatted@3.3.1: {}
+
+  fn.name@1.1.0: {}
+
+  follow-redirects@1.15.6: {}
+
+  foreground-child@3.2.1:
+    dependencies:
+      cross-spawn: 7.0.3
+      signal-exit: 4.1.0
+
+  fork-ts-checker-webpack-plugin@9.0.2(typescript@5.3.3)(webpack@5.92.1):
+    dependencies:
+      '@babel/code-frame': 7.24.7
+      chalk: 4.1.2
+      chokidar: 3.6.0
+      cosmiconfig: 8.3.6(typescript@5.3.3)
+      deepmerge: 4.3.1
+      fs-extra: 10.1.0
+      memfs: 3.5.3
+      minimatch: 3.1.2
+      node-abort-controller: 3.1.1
+      schema-utils: 3.3.0
+      semver: 7.6.2
+      tapable: 2.2.1
+      typescript: 5.3.3
+      webpack: 5.92.1
+
+  form-data@4.0.0:
+    dependencies:
+      asynckit: 0.4.0
+      combined-stream: 1.0.8
+      mime-types: 2.1.35
+
+  formidable@3.5.1:
+    dependencies:
+      dezalgo: 1.0.4
+      hexoid: 1.0.0
+      once: 1.4.0
+
+  forwarded@0.2.0: {}
+
+  frac@1.1.2: {}
+
+  fresh@0.5.2: {}
+
+  fs-extra@10.1.0:
+    dependencies:
+      graceful-fs: 4.2.11
+      jsonfile: 6.1.0
+      universalify: 2.0.1
+
+  fs-monkey@1.0.6: {}
+
+  fs.realpath@1.0.0: {}
+
+  fsevents@2.3.3:
+    optional: true
+
+  function-bind@1.1.2: {}
+
+  gensync@1.0.0-beta.2: {}
+
+  get-caller-file@2.0.5: {}
+
+  get-intrinsic@1.2.4:
+    dependencies:
+      es-errors: 1.3.0
+      function-bind: 1.1.2
+      has-proto: 1.0.3
+      has-symbols: 1.0.3
+      hasown: 2.0.2
+
+  get-package-type@0.1.0: {}
+
+  get-stream@6.0.1: {}
+
+  glob-parent@5.1.2:
+    dependencies:
+      is-glob: 4.0.3
+
+  glob-parent@6.0.2:
+    dependencies:
+      is-glob: 4.0.3
+
+  glob-to-regexp@0.4.1: {}
+
+  glob@10.4.2:
+    dependencies:
+      foreground-child: 3.2.1
+      jackspeak: 3.4.2
+      minimatch: 9.0.5
+      minipass: 7.1.2
+      package-json-from-dist: 1.0.0
+      path-scurry: 1.11.1
+
+  glob@7.2.3:
+    dependencies:
+      fs.realpath: 1.0.0
+      inflight: 1.0.6
+      inherits: 2.0.4
+      minimatch: 3.1.2
+      once: 1.4.0
+      path-is-absolute: 1.0.1
+
+  globals@11.12.0: {}
+
+  globals@13.24.0:
+    dependencies:
+      type-fest: 0.20.2
+
+  globby@11.1.0:
+    dependencies:
+      array-union: 2.1.0
+      dir-glob: 3.0.1
+      fast-glob: 3.3.2
+      ignore: 5.3.1
+      merge2: 1.4.1
+      slash: 3.0.0
+
+  gopd@1.0.1:
+    dependencies:
+      get-intrinsic: 1.2.4
+
+  graceful-fs@4.2.11: {}
+
+  graphemer@1.4.0: {}
+
+  has-flag@3.0.0: {}
+
+  has-flag@4.0.0: {}
+
+  has-own-prop@2.0.0: {}
+
+  has-property-descriptors@1.0.2:
+    dependencies:
+      es-define-property: 1.0.0
+
+  has-proto@1.0.3: {}
+
+  has-symbols@1.0.3: {}
+
+  hasown@2.0.2:
+    dependencies:
+      function-bind: 1.1.2
+
+  hexoid@1.0.0: {}
+
+  html-escaper@2.0.2: {}
+
+  http-errors@2.0.0:
+    dependencies:
+      depd: 2.0.0
+      inherits: 2.0.4
+      setprototypeof: 1.2.0
+      statuses: 2.0.1
+      toidentifier: 1.0.1
+
+  human-signals@2.1.0: {}
+
+  iconv-lite@0.4.24:
+    dependencies:
+      safer-buffer: 2.1.2
+
+  ieee754@1.2.1: {}
+
+  ignore@5.3.1: {}
+
+  import-fresh@3.3.0:
+    dependencies:
+      parent-module: 1.0.1
+      resolve-from: 4.0.0
+
+  import-local@3.1.0:
+    dependencies:
+      pkg-dir: 4.2.0
+      resolve-cwd: 3.0.0
+
+  imurmurhash@0.1.4: {}
+
+  inflight@1.0.6:
+    dependencies:
+      once: 1.4.0
+      wrappy: 1.0.2
+
+  inherits@2.0.4: {}
+
+  inquirer@8.2.6:
+    dependencies:
+      ansi-escapes: 4.3.2
+      chalk: 4.1.2
+      cli-cursor: 3.1.0
+      cli-width: 3.0.0
+      external-editor: 3.1.0
+      figures: 3.2.0
+      lodash: 4.17.21
+      mute-stream: 0.0.8
+      ora: 5.4.1
+      run-async: 2.4.1
+      rxjs: 7.8.1
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+      through: 2.3.8
+      wrap-ansi: 6.2.0
+
+  inquirer@9.2.15:
+    dependencies:
+      '@ljharb/through': 2.3.13
+      ansi-escapes: 4.3.2
+      chalk: 5.3.0
+      cli-cursor: 3.1.0
+      cli-width: 4.1.0
+      external-editor: 3.1.0
+      figures: 3.2.0
+      lodash: 4.17.21
+      mute-stream: 1.0.0
+      ora: 5.4.1
+      run-async: 3.0.0
+      rxjs: 7.8.1
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+      wrap-ansi: 6.2.0
+
+  ipaddr.js@1.9.1: {}
+
+  is-arrayish@0.2.1: {}
+
+  is-arrayish@0.3.2: {}
+
+  is-binary-path@2.1.0:
+    dependencies:
+      binary-extensions: 2.3.0
+
+  is-core-module@2.14.0:
+    dependencies:
+      hasown: 2.0.2
+
+  is-extglob@2.1.1: {}
+
+  is-fullwidth-code-point@3.0.0: {}
+
+  is-generator-fn@2.1.0: {}
+
+  is-glob@4.0.3:
+    dependencies:
+      is-extglob: 2.1.1
+
+  is-interactive@1.0.0: {}
+
+  is-number@7.0.0: {}
+
+  is-path-inside@3.0.3: {}
+
+  is-stream@2.0.1: {}
+
+  is-unicode-supported@0.1.0: {}
+
+  isarray@1.0.0: {}
+
+  isexe@2.0.0: {}
+
+  istanbul-lib-coverage@3.2.2: {}
+
+  istanbul-lib-instrument@5.2.1:
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/parser': 7.24.7
+      '@istanbuljs/schema': 0.1.3
+      istanbul-lib-coverage: 3.2.2
+      semver: 6.3.1
+    transitivePeerDependencies:
+      - supports-color
+
+  istanbul-lib-instrument@6.0.3:
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/parser': 7.24.7
+      '@istanbuljs/schema': 0.1.3
+      istanbul-lib-coverage: 3.2.2
+      semver: 7.6.2
+    transitivePeerDependencies:
+      - supports-color
+
+  istanbul-lib-report@3.0.1:
+    dependencies:
+      istanbul-lib-coverage: 3.2.2
+      make-dir: 4.0.0
+      supports-color: 7.2.0
+
+  istanbul-lib-source-maps@4.0.1:
+    dependencies:
+      debug: 4.3.5
+      istanbul-lib-coverage: 3.2.2
+      source-map: 0.6.1
+    transitivePeerDependencies:
+      - supports-color
+
+  istanbul-reports@3.1.7:
+    dependencies:
+      html-escaper: 2.0.2
+      istanbul-lib-report: 3.0.1
+
+  iterare@1.2.1: {}
+
+  jackspeak@3.4.2:
+    dependencies:
+      '@isaacs/cliui': 8.0.2
+    optionalDependencies:
+      '@pkgjs/parseargs': 0.11.0
+
+  jest-changed-files@29.7.0:
+    dependencies:
+      execa: 5.1.1
+      jest-util: 29.7.0
+      p-limit: 3.1.0
+
+  jest-circus@29.7.0:
+    dependencies:
+      '@jest/environment': 29.7.0
+      '@jest/expect': 29.7.0
+      '@jest/test-result': 29.7.0
+      '@jest/types': 29.6.3
+      '@types/node': 20.14.10
+      chalk: 4.1.2
+      co: 4.6.0
+      dedent: 1.5.3
+      is-generator-fn: 2.1.0
+      jest-each: 29.7.0
+      jest-matcher-utils: 29.7.0
+      jest-message-util: 29.7.0
+      jest-runtime: 29.7.0
+      jest-snapshot: 29.7.0
+      jest-util: 29.7.0
+      p-limit: 3.1.0
+      pretty-format: 29.7.0
+      pure-rand: 6.1.0
+      slash: 3.0.0
+      stack-utils: 2.0.6
+    transitivePeerDependencies:
+      - babel-plugin-macros
+      - supports-color
+
+  jest-cli@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)):
+    dependencies:
+      '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))
+      '@jest/test-result': 29.7.0
+      '@jest/types': 29.6.3
+      chalk: 4.1.2
+      create-jest: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))
+      exit: 0.1.2
+      import-local: 3.1.0
+      jest-config: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))
+      jest-util: 29.7.0
+      jest-validate: 29.7.0
+      yargs: 17.7.2
+    transitivePeerDependencies:
+      - '@types/node'
+      - babel-plugin-macros
+      - supports-color
+      - ts-node
+
+  jest-config@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)):
+    dependencies:
+      '@babel/core': 7.24.7
+      '@jest/test-sequencer': 29.7.0
+      '@jest/types': 29.6.3
+      babel-jest: 29.7.0(@babel/core@7.24.7)
+      chalk: 4.1.2
+      ci-info: 3.9.0
+      deepmerge: 4.3.1
+      glob: 7.2.3
+      graceful-fs: 4.2.11
+      jest-circus: 29.7.0
+      jest-environment-node: 29.7.0
+      jest-get-type: 29.6.3
+      jest-regex-util: 29.6.3
+      jest-resolve: 29.7.0
+      jest-runner: 29.7.0
+      jest-util: 29.7.0
+      jest-validate: 29.7.0
+      micromatch: 4.0.7
+      parse-json: 5.2.0
+      pretty-format: 29.7.0
+      slash: 3.0.0
+      strip-json-comments: 3.1.1
+    optionalDependencies:
+      '@types/node': 20.14.10
+      ts-node: 10.9.2(@types/node@20.14.10)(typescript@5.5.3)
+    transitivePeerDependencies:
+      - babel-plugin-macros
+      - supports-color
+
+  jest-diff@29.7.0:
+    dependencies:
+      chalk: 4.1.2
+      diff-sequences: 29.6.3
+      jest-get-type: 29.6.3
+      pretty-format: 29.7.0
+
+  jest-docblock@29.7.0:
+    dependencies:
+      detect-newline: 3.1.0
+
+  jest-each@29.7.0:
+    dependencies:
+      '@jest/types': 29.6.3
+      chalk: 4.1.2
+      jest-get-type: 29.6.3
+      jest-util: 29.7.0
+      pretty-format: 29.7.0
+
+  jest-environment-node@29.7.0:
+    dependencies:
+      '@jest/environment': 29.7.0
+      '@jest/fake-timers': 29.7.0
+      '@jest/types': 29.6.3
+      '@types/node': 20.14.10
+      jest-mock: 29.7.0
+      jest-util: 29.7.0
+
+  jest-get-type@29.6.3: {}
+
+  jest-haste-map@29.7.0:
+    dependencies:
+      '@jest/types': 29.6.3
+      '@types/graceful-fs': 4.1.9
+      '@types/node': 20.14.10
+      anymatch: 3.1.3
+      fb-watchman: 2.0.2
+      graceful-fs: 4.2.11
+      jest-regex-util: 29.6.3
+      jest-util: 29.7.0
+      jest-worker: 29.7.0
+      micromatch: 4.0.7
+      walker: 1.0.8
+    optionalDependencies:
+      fsevents: 2.3.3
+
+  jest-leak-detector@29.7.0:
+    dependencies:
+      jest-get-type: 29.6.3
+      pretty-format: 29.7.0
+
+  jest-matcher-utils@29.7.0:
+    dependencies:
+      chalk: 4.1.2
+      jest-diff: 29.7.0
+      jest-get-type: 29.6.3
+      pretty-format: 29.7.0
+
+  jest-message-util@29.7.0:
+    dependencies:
+      '@babel/code-frame': 7.24.7
+      '@jest/types': 29.6.3
+      '@types/stack-utils': 2.0.3
+      chalk: 4.1.2
+      graceful-fs: 4.2.11
+      micromatch: 4.0.7
+      pretty-format: 29.7.0
+      slash: 3.0.0
+      stack-utils: 2.0.6
+
+  jest-mock@29.7.0:
+    dependencies:
+      '@jest/types': 29.6.3
+      '@types/node': 20.14.10
+      jest-util: 29.7.0
+
+  jest-pnp-resolver@1.2.3(jest-resolve@29.7.0):
+    optionalDependencies:
+      jest-resolve: 29.7.0
+
+  jest-regex-util@29.6.3: {}
+
+  jest-resolve-dependencies@29.7.0:
+    dependencies:
+      jest-regex-util: 29.6.3
+      jest-snapshot: 29.7.0
+    transitivePeerDependencies:
+      - supports-color
+
+  jest-resolve@29.7.0:
+    dependencies:
+      chalk: 4.1.2
+      graceful-fs: 4.2.11
+      jest-haste-map: 29.7.0
+      jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0)
+      jest-util: 29.7.0
+      jest-validate: 29.7.0
+      resolve: 1.22.8
+      resolve.exports: 2.0.2
+      slash: 3.0.0
+
+  jest-runner@29.7.0:
+    dependencies:
+      '@jest/console': 29.7.0
+      '@jest/environment': 29.7.0
+      '@jest/test-result': 29.7.0
+      '@jest/transform': 29.7.0
+      '@jest/types': 29.6.3
+      '@types/node': 20.14.10
+      chalk: 4.1.2
+      emittery: 0.13.1
+      graceful-fs: 4.2.11
+      jest-docblock: 29.7.0
+      jest-environment-node: 29.7.0
+      jest-haste-map: 29.7.0
+      jest-leak-detector: 29.7.0
+      jest-message-util: 29.7.0
+      jest-resolve: 29.7.0
+      jest-runtime: 29.7.0
+      jest-util: 29.7.0
+      jest-watcher: 29.7.0
+      jest-worker: 29.7.0
+      p-limit: 3.1.0
+      source-map-support: 0.5.13
+    transitivePeerDependencies:
+      - supports-color
+
+  jest-runtime@29.7.0:
+    dependencies:
+      '@jest/environment': 29.7.0
+      '@jest/fake-timers': 29.7.0
+      '@jest/globals': 29.7.0
+      '@jest/source-map': 29.6.3
+      '@jest/test-result': 29.7.0
+      '@jest/transform': 29.7.0
+      '@jest/types': 29.6.3
+      '@types/node': 20.14.10
+      chalk: 4.1.2
+      cjs-module-lexer: 1.3.1
+      collect-v8-coverage: 1.0.2
+      glob: 7.2.3
+      graceful-fs: 4.2.11
+      jest-haste-map: 29.7.0
+      jest-message-util: 29.7.0
+      jest-mock: 29.7.0
+      jest-regex-util: 29.6.3
+      jest-resolve: 29.7.0
+      jest-snapshot: 29.7.0
+      jest-util: 29.7.0
+      slash: 3.0.0
+      strip-bom: 4.0.0
+    transitivePeerDependencies:
+      - supports-color
+
+  jest-snapshot@29.7.0:
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/generator': 7.24.7
+      '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.24.7)
+      '@babel/plugin-syntax-typescript': 7.24.7(@babel/core@7.24.7)
+      '@babel/types': 7.24.7
+      '@jest/expect-utils': 29.7.0
+      '@jest/transform': 29.7.0
+      '@jest/types': 29.6.3
+      babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.7)
+      chalk: 4.1.2
+      expect: 29.7.0
+      graceful-fs: 4.2.11
+      jest-diff: 29.7.0
+      jest-get-type: 29.6.3
+      jest-matcher-utils: 29.7.0
+      jest-message-util: 29.7.0
+      jest-util: 29.7.0
+      natural-compare: 1.4.0
+      pretty-format: 29.7.0
+      semver: 7.6.2
+    transitivePeerDependencies:
+      - supports-color
+
+  jest-util@29.7.0:
+    dependencies:
+      '@jest/types': 29.6.3
+      '@types/node': 20.14.10
+      chalk: 4.1.2
+      ci-info: 3.9.0
+      graceful-fs: 4.2.11
+      picomatch: 2.3.1
+
+  jest-validate@29.7.0:
+    dependencies:
+      '@jest/types': 29.6.3
+      camelcase: 6.3.0
+      chalk: 4.1.2
+      jest-get-type: 29.6.3
+      leven: 3.1.0
+      pretty-format: 29.7.0
+
+  jest-watcher@29.7.0:
+    dependencies:
+      '@jest/test-result': 29.7.0
+      '@jest/types': 29.6.3
+      '@types/node': 20.14.10
+      ansi-escapes: 4.3.2
+      chalk: 4.1.2
+      emittery: 0.13.1
+      jest-util: 29.7.0
+      string-length: 4.0.2
+
+  jest-worker@27.5.1:
+    dependencies:
+      '@types/node': 20.14.10
+      merge-stream: 2.0.0
+      supports-color: 8.1.1
+
+  jest-worker@29.7.0:
+    dependencies:
+      '@types/node': 20.14.10
+      jest-util: 29.7.0
+      merge-stream: 2.0.0
+      supports-color: 8.1.1
+
+  jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)):
+    dependencies:
+      '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))
+      '@jest/types': 29.6.3
+      import-local: 3.1.0
+      jest-cli: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))
+    transitivePeerDependencies:
+      - '@types/node'
+      - babel-plugin-macros
+      - supports-color
+      - ts-node
+
+  js-tokens@4.0.0: {}
+
+  js-yaml@3.14.1:
+    dependencies:
+      argparse: 1.0.10
+      esprima: 4.0.1
+
+  js-yaml@4.1.0:
+    dependencies:
+      argparse: 2.0.1
+
+  jsesc@2.5.2: {}
+
+  json-buffer@3.0.1: {}
+
+  json-parse-even-better-errors@2.3.1: {}
+
+  json-schema-traverse@0.4.1: {}
+
+  json-schema-traverse@1.0.0: {}
+
+  json-stable-stringify-without-jsonify@1.0.1: {}
+
+  json5@2.2.3: {}
+
+  jsonc-parser@3.2.1: {}
+
+  jsonc-parser@3.3.1: {}
+
+  jsonfile@6.1.0:
+    dependencies:
+      universalify: 2.0.1
+    optionalDependencies:
+      graceful-fs: 4.2.11
+
+  jsonwebtoken@9.0.2:
+    dependencies:
+      jws: 3.2.2
+      lodash.includes: 4.3.0
+      lodash.isboolean: 3.0.3
+      lodash.isinteger: 4.0.4
+      lodash.isnumber: 3.0.3
+      lodash.isplainobject: 4.0.6
+      lodash.isstring: 4.0.1
+      lodash.once: 4.1.1
+      ms: 2.1.3
+      semver: 7.6.2
+
+  jwa@1.4.1:
+    dependencies:
+      buffer-equal-constant-time: 1.0.1
+      ecdsa-sig-formatter: 1.0.11
+      safe-buffer: 5.2.1
+
+  jws@3.2.2:
+    dependencies:
+      jwa: 1.4.1
+      safe-buffer: 5.2.1
+
+  keyv@4.5.4:
+    dependencies:
+      json-buffer: 3.0.1
+
+  kleur@3.0.3: {}
+
+  kuler@2.0.0: {}
+
+  leven@3.1.0: {}
+
+  levn@0.4.1:
+    dependencies:
+      prelude-ls: 1.2.1
+      type-check: 0.4.0
+
+  libphonenumber-js@1.11.4: {}
+
+  lines-and-columns@1.2.4: {}
+
+  loader-runner@4.3.0: {}
+
+  locate-path@5.0.0:
+    dependencies:
+      p-locate: 4.1.0
+
+  locate-path@6.0.0:
+    dependencies:
+      p-locate: 5.0.0
+
+  lodash.includes@4.3.0: {}
+
+  lodash.isboolean@3.0.3: {}
+
+  lodash.isinteger@4.0.4: {}
+
+  lodash.isnumber@3.0.3: {}
+
+  lodash.isplainobject@4.0.6: {}
+
+  lodash.isstring@4.0.1: {}
+
+  lodash.memoize@4.1.2: {}
+
+  lodash.merge@4.6.2: {}
+
+  lodash.once@4.1.1: {}
+
+  lodash@4.17.21: {}
+
+  log-symbols@4.1.0:
+    dependencies:
+      chalk: 4.1.2
+      is-unicode-supported: 0.1.0
+
+  logform@2.6.1:
+    dependencies:
+      '@colors/colors': 1.6.0
+      '@types/triple-beam': 1.3.5
+      fecha: 4.2.3
+      ms: 2.1.3
+      safe-stable-stringify: 2.5.0
+      triple-beam: 1.4.1
+
+  lru-cache@10.4.2: {}
+
+  lru-cache@5.1.1:
+    dependencies:
+      yallist: 3.1.1
+
+  magic-string@0.30.8:
+    dependencies:
+      '@jridgewell/sourcemap-codec': 1.4.15
+
+  make-dir@4.0.0:
+    dependencies:
+      semver: 7.6.2
+
+  make-error@1.3.6: {}
+
+  makeerror@1.0.12:
+    dependencies:
+      tmpl: 1.0.5
+
+  media-typer@0.3.0: {}
+
+  memfs@3.5.3:
+    dependencies:
+      fs-monkey: 1.0.6
+
+  merge-descriptors@1.0.1: {}
+
+  merge-stream@2.0.0: {}
+
+  merge2@1.4.1: {}
+
+  methods@1.1.2: {}
+
+  micromatch@4.0.7:
+    dependencies:
+      braces: 3.0.3
+      picomatch: 2.3.1
+
+  mime-db@1.52.0: {}
+
+  mime-types@2.1.35:
+    dependencies:
+      mime-db: 1.52.0
+
+  mime@1.6.0: {}
+
+  mime@2.6.0: {}
+
+  mimic-fn@2.1.0: {}
+
+  minimatch@3.1.2:
+    dependencies:
+      brace-expansion: 1.1.11
+
+  minimatch@9.0.5:
+    dependencies:
+      brace-expansion: 2.0.1
+
+  minimist@1.2.8: {}
+
+  minipass@7.1.2: {}
+
+  mkdirp@0.5.6:
+    dependencies:
+      minimist: 1.2.8
+
+  moment@2.30.1: {}
+
+  ms@2.0.0: {}
+
+  ms@2.1.2: {}
+
+  ms@2.1.3: {}
+
+  multer@1.4.4-lts.1:
+    dependencies:
+      append-field: 1.0.0
+      busboy: 1.6.0
+      concat-stream: 1.6.2
+      mkdirp: 0.5.6
+      object-assign: 4.1.1
+      type-is: 1.6.18
+      xtend: 4.0.2
+
+  multer@1.4.5-lts.1:
+    dependencies:
+      append-field: 1.0.0
+      busboy: 1.6.0
+      concat-stream: 1.6.2
+      mkdirp: 0.5.6
+      object-assign: 4.1.1
+      type-is: 1.6.18
+      xtend: 4.0.2
+
+  mute-stream@0.0.8: {}
+
+  mute-stream@1.0.0: {}
+
+  natural-compare@1.4.0: {}
+
+  negotiator@0.6.3: {}
+
+  neo-async@2.6.2: {}
+
+  nest-winston@1.9.7(@nestjs/common@10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(winston@3.14.2):
+    dependencies:
+      '@nestjs/common': 10.3.10(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      fast-safe-stringify: 2.1.1
+      winston: 3.14.2
+
+  node-abort-controller@3.1.1: {}
+
+  node-emoji@1.11.0:
+    dependencies:
+      lodash: 4.17.21
+
+  node-fetch@2.7.0:
+    dependencies:
+      whatwg-url: 5.0.0
+
+  node-int64@0.4.0: {}
+
+  node-releases@2.0.14: {}
+
+  normalize-path@3.0.0: {}
+
+  npm-run-path@4.0.1:
+    dependencies:
+      path-key: 3.1.1
+
+  object-assign@4.1.1: {}
+
+  object-hash@3.0.0: {}
+
+  object-inspect@1.13.2: {}
+
+  on-finished@2.4.1:
+    dependencies:
+      ee-first: 1.1.1
+
+  on-headers@1.0.2: {}
+
+  once@1.4.0:
+    dependencies:
+      wrappy: 1.0.2
+
+  one-time@1.0.0:
+    dependencies:
+      fn.name: 1.1.0
+
+  onetime@5.1.2:
+    dependencies:
+      mimic-fn: 2.1.0
+
+  opentype.js@0.7.3:
+    dependencies:
+      tiny-inflate: 1.0.3
+
+  optionator@0.9.4:
+    dependencies:
+      deep-is: 0.1.4
+      fast-levenshtein: 2.0.6
+      levn: 0.4.1
+      prelude-ls: 1.2.1
+      type-check: 0.4.0
+      word-wrap: 1.2.5
+
+  ora@5.4.1:
+    dependencies:
+      bl: 4.1.0
+      chalk: 4.1.2
+      cli-cursor: 3.1.0
+      cli-spinners: 2.9.2
+      is-interactive: 1.0.0
+      is-unicode-supported: 0.1.0
+      log-symbols: 4.1.0
+      strip-ansi: 6.0.1
+      wcwidth: 1.0.1
+
+  os-tmpdir@1.0.2: {}
+
+  p-limit@2.3.0:
+    dependencies:
+      p-try: 2.2.0
+
+  p-limit@3.1.0:
+    dependencies:
+      yocto-queue: 0.1.0
+
+  p-locate@4.1.0:
+    dependencies:
+      p-limit: 2.3.0
+
+  p-locate@5.0.0:
+    dependencies:
+      p-limit: 3.1.0
+
+  p-try@2.2.0: {}
+
+  package-json-from-dist@1.0.0: {}
+
+  parent-module@1.0.1:
+    dependencies:
+      callsites: 3.1.0
+
+  parse-json@5.2.0:
+    dependencies:
+      '@babel/code-frame': 7.24.7
+      error-ex: 1.3.2
+      json-parse-even-better-errors: 2.3.1
+      lines-and-columns: 1.2.4
+
+  parseurl@1.3.3: {}
+
+  passport-jwt@4.0.1:
+    dependencies:
+      jsonwebtoken: 9.0.2
+      passport-strategy: 1.0.0
+
+  passport-strategy@1.0.0: {}
+
+  passport@0.7.0:
+    dependencies:
+      passport-strategy: 1.0.0
+      pause: 0.0.1
+      utils-merge: 1.0.1
+
+  path-exists@4.0.0: {}
+
+  path-is-absolute@1.0.1: {}
+
+  path-key@3.1.1: {}
+
+  path-parse@1.0.7: {}
+
+  path-scurry@1.11.1:
+    dependencies:
+      lru-cache: 10.4.2
+      minipass: 7.1.2
+
+  path-to-regexp@0.1.7: {}
+
+  path-to-regexp@3.2.0: {}
+
+  path-type@4.0.0: {}
+
+  pause@0.0.1: {}
+
+  picocolors@1.0.1: {}
+
+  picomatch@2.3.1: {}
+
+  picomatch@4.0.1: {}
+
+  pirates@4.0.6: {}
+
+  pkg-dir@4.2.0:
+    dependencies:
+      find-up: 4.1.0
+
+  pluralize@8.0.0: {}
+
+  prelude-ls@1.2.1: {}
+
+  prettier-linter-helpers@1.0.0:
+    dependencies:
+      fast-diff: 1.3.0
+
+  prettier@3.3.2: {}
+
+  pretty-format@29.7.0:
+    dependencies:
+      '@jest/schemas': 29.6.3
+      ansi-styles: 5.2.0
+      react-is: 18.3.1
+
+  prisma@5.16.1:
+    dependencies:
+      '@prisma/engines': 5.16.1
+
+  process-nextick-args@2.0.1: {}
+
+  prompts@2.4.2:
+    dependencies:
+      kleur: 3.0.3
+      sisteransi: 1.0.5
+
+  proxy-addr@2.0.7:
+    dependencies:
+      forwarded: 0.2.0
+      ipaddr.js: 1.9.1
+
+  proxy-from-env@1.1.0: {}
+
+  punycode@2.3.1: {}
+
+  pure-rand@6.1.0: {}
+
+  qs@6.11.0:
+    dependencies:
+      side-channel: 1.0.6
+
+  qs@6.12.3:
+    dependencies:
+      side-channel: 1.0.6
+
+  queue-microtask@1.2.3: {}
+
+  random-bytes@1.0.0: {}
+
+  randombytes@2.1.0:
+    dependencies:
+      safe-buffer: 5.2.1
+
+  range-parser@1.2.1: {}
+
+  raw-body@2.5.2:
+    dependencies:
+      bytes: 3.1.2
+      http-errors: 2.0.0
+      iconv-lite: 0.4.24
+      unpipe: 1.0.0
+
+  react-is@18.3.1: {}
+
+  readable-stream@2.3.8:
+    dependencies:
+      core-util-is: 1.0.3
+      inherits: 2.0.4
+      isarray: 1.0.0
+      process-nextick-args: 2.0.1
+      safe-buffer: 5.1.2
+      string_decoder: 1.1.1
+      util-deprecate: 1.0.2
+
+  readable-stream@3.6.2:
+    dependencies:
+      inherits: 2.0.4
+      string_decoder: 1.3.0
+      util-deprecate: 1.0.2
+
+  readdirp@3.6.0:
+    dependencies:
+      picomatch: 2.3.1
+
+  reflect-metadata@0.2.2: {}
+
+  repeat-string@1.6.1: {}
+
+  require-directory@2.1.1: {}
+
+  require-from-string@2.0.2: {}
+
+  resolve-cwd@3.0.0:
+    dependencies:
+      resolve-from: 5.0.0
+
+  resolve-from@4.0.0: {}
+
+  resolve-from@5.0.0: {}
+
+  resolve.exports@2.0.2: {}
+
+  resolve@1.22.8:
+    dependencies:
+      is-core-module: 2.14.0
+      path-parse: 1.0.7
+      supports-preserve-symlinks-flag: 1.0.0
+
+  restore-cursor@3.1.0:
+    dependencies:
+      onetime: 5.1.2
+      signal-exit: 3.0.7
+
+  reusify@1.0.4: {}
+
+  rimraf@3.0.2:
+    dependencies:
+      glob: 7.2.3
+
+  run-async@2.4.1: {}
+
+  run-async@3.0.0: {}
+
+  run-parallel@1.2.0:
+    dependencies:
+      queue-microtask: 1.2.3
+
+  run-script-webpack-plugin@0.2.0: {}
+
+  rxjs@7.8.1:
+    dependencies:
+      tslib: 2.6.3
+
+  safe-buffer@5.1.2: {}
+
+  safe-buffer@5.2.1: {}
+
+  safe-stable-stringify@2.5.0: {}
+
+  safer-buffer@2.1.2: {}
+
+  schema-utils@3.3.0:
+    dependencies:
+      '@types/json-schema': 7.0.15
+      ajv: 6.12.6
+      ajv-keywords: 3.5.2(ajv@6.12.6)
+
+  semver@6.3.1: {}
+
+  semver@7.6.2: {}
+
+  send@0.18.0:
+    dependencies:
+      debug: 2.6.9
+      depd: 2.0.0
+      destroy: 1.2.0
+      encodeurl: 1.0.2
+      escape-html: 1.0.3
+      etag: 1.8.1
+      fresh: 0.5.2
+      http-errors: 2.0.0
+      mime: 1.6.0
+      ms: 2.1.3
+      on-finished: 2.4.1
+      range-parser: 1.2.1
+      statuses: 2.0.1
+    transitivePeerDependencies:
+      - supports-color
+
+  serialize-javascript@6.0.2:
+    dependencies:
+      randombytes: 2.1.0
+
+  serve-static@1.15.0:
+    dependencies:
+      encodeurl: 1.0.2
+      escape-html: 1.0.3
+      parseurl: 1.3.3
+      send: 0.18.0
+    transitivePeerDependencies:
+      - supports-color
+
+  set-function-length@1.2.2:
+    dependencies:
+      define-data-property: 1.1.4
+      es-errors: 1.3.0
+      function-bind: 1.1.2
+      get-intrinsic: 1.2.4
+      gopd: 1.0.1
+      has-property-descriptors: 1.0.2
+
+  setprototypeof@1.2.0: {}
+
+  shebang-command@2.0.0:
+    dependencies:
+      shebang-regex: 3.0.0
+
+  shebang-regex@3.0.0: {}
+
+  side-channel@1.0.6:
+    dependencies:
+      call-bind: 1.0.7
+      es-errors: 1.3.0
+      get-intrinsic: 1.2.4
+      object-inspect: 1.13.2
+
+  signal-exit@3.0.7: {}
+
+  signal-exit@4.1.0: {}
+
+  simple-swizzle@0.2.2:
+    dependencies:
+      is-arrayish: 0.3.2
+
+  sisteransi@1.0.5: {}
+
+  slash@3.0.0: {}
+
+  source-map-support@0.5.13:
+    dependencies:
+      buffer-from: 1.1.2
+      source-map: 0.6.1
+
+  source-map-support@0.5.21:
+    dependencies:
+      buffer-from: 1.1.2
+      source-map: 0.6.1
+
+  source-map@0.6.1: {}
+
+  source-map@0.7.4: {}
+
+  sprintf-js@1.0.3: {}
+
+  ssf@0.11.2:
+    dependencies:
+      frac: 1.1.2
+
+  stack-trace@0.0.10: {}
+
+  stack-utils@2.0.6:
+    dependencies:
+      escape-string-regexp: 2.0.0
+
+  statuses@2.0.1: {}
+
+  streamsearch@1.1.0: {}
+
+  string-length@4.0.2:
+    dependencies:
+      char-regex: 1.0.2
+      strip-ansi: 6.0.1
+
+  string-width@4.2.3:
+    dependencies:
+      emoji-regex: 8.0.0
+      is-fullwidth-code-point: 3.0.0
+      strip-ansi: 6.0.1
+
+  string-width@5.1.2:
+    dependencies:
+      eastasianwidth: 0.2.0
+      emoji-regex: 9.2.2
+      strip-ansi: 7.1.0
+
+  string_decoder@1.1.1:
+    dependencies:
+      safe-buffer: 5.1.2
+
+  string_decoder@1.3.0:
+    dependencies:
+      safe-buffer: 5.2.1
+
+  strip-ansi@6.0.1:
+    dependencies:
+      ansi-regex: 5.0.1
+
+  strip-ansi@7.1.0:
+    dependencies:
+      ansi-regex: 6.0.1
+
+  strip-bom@3.0.0: {}
+
+  strip-bom@4.0.0: {}
+
+  strip-final-newline@2.0.0: {}
+
+  strip-json-comments@3.1.1: {}
+
+  superagent@9.0.2:
+    dependencies:
+      component-emitter: 1.3.1
+      cookiejar: 2.1.4
+      debug: 4.3.5
+      fast-safe-stringify: 2.1.1
+      form-data: 4.0.0
+      formidable: 3.5.1
+      methods: 1.1.2
+      mime: 2.6.0
+      qs: 6.12.3
+    transitivePeerDependencies:
+      - supports-color
+
+  supertest@7.0.0:
+    dependencies:
+      methods: 1.1.2
+      superagent: 9.0.2
+    transitivePeerDependencies:
+      - supports-color
+
+  supports-color@5.5.0:
+    dependencies:
+      has-flag: 3.0.0
+
+  supports-color@7.2.0:
+    dependencies:
+      has-flag: 4.0.0
+
+  supports-color@8.1.1:
+    dependencies:
+      has-flag: 4.0.0
+
+  supports-preserve-symlinks-flag@1.0.0: {}
+
+  svg-captcha@1.4.0:
+    dependencies:
+      opentype.js: 0.7.3
+
+  swagger-ui-dist@5.17.14: {}
+
+  swagger-ui-express@5.0.1(express@4.19.2):
+    dependencies:
+      express: 4.19.2
+      swagger-ui-dist: 5.17.14
+
+  symbol-observable@4.0.0: {}
+
+  synckit@0.8.8:
+    dependencies:
+      '@pkgr/core': 0.1.1
+      tslib: 2.6.3
+
+  tapable@2.2.1: {}
+
+  terser-webpack-plugin@5.3.10(webpack@5.92.1):
+    dependencies:
+      '@jridgewell/trace-mapping': 0.3.25
+      jest-worker: 27.5.1
+      schema-utils: 3.3.0
+      serialize-javascript: 6.0.2
+      terser: 5.31.1
+      webpack: 5.92.1
+
+  terser-webpack-plugin@5.3.10(webpack@5.94.0):
+    dependencies:
+      '@jridgewell/trace-mapping': 0.3.25
+      jest-worker: 27.5.1
+      schema-utils: 3.3.0
+      serialize-javascript: 6.0.2
+      terser: 5.31.1
+      webpack: 5.94.0
+
+  terser@5.31.1:
+    dependencies:
+      '@jridgewell/source-map': 0.3.6
+      acorn: 8.12.1
+      commander: 2.20.3
+      source-map-support: 0.5.21
+
+  test-exclude@6.0.0:
+    dependencies:
+      '@istanbuljs/schema': 0.1.3
+      glob: 7.2.3
+      minimatch: 3.1.2
+
+  text-hex@1.0.0: {}
+
+  text-table@0.2.0: {}
+
+  through@2.3.8: {}
+
+  tiny-inflate@1.0.3: {}
+
+  tmp@0.0.33:
+    dependencies:
+      os-tmpdir: 1.0.2
+
+  tmpl@1.0.5: {}
+
+  to-fast-properties@2.0.0: {}
+
+  to-regex-range@5.0.1:
+    dependencies:
+      is-number: 7.0.0
+
+  toidentifier@1.0.1: {}
+
+  tr46@0.0.3: {}
+
+  tree-kill@1.2.2: {}
+
+  triple-beam@1.4.1: {}
+
+  ts-api-utils@1.3.0(typescript@5.5.3):
+    dependencies:
+      typescript: 5.5.3
+
+  ts-jest@29.2.0(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@5.5.3):
+    dependencies:
+      bs-logger: 0.2.6
+      fast-json-stable-stringify: 2.1.0
+      jest: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))
+      jest-util: 29.7.0
+      json5: 2.2.3
+      lodash.memoize: 4.1.2
+      make-error: 1.3.6
+      semver: 7.6.2
+      typescript: 5.5.3
+      yargs-parser: 21.1.1
+    optionalDependencies:
+      '@babel/core': 7.24.7
+      '@jest/transform': 29.7.0
+      '@jest/types': 29.6.3
+      babel-jest: 29.7.0(@babel/core@7.24.7)
+
+  ts-loader@9.5.1(typescript@5.5.3)(webpack@5.94.0):
+    dependencies:
+      chalk: 4.1.2
+      enhanced-resolve: 5.17.0
+      micromatch: 4.0.7
+      semver: 7.6.2
+      source-map: 0.7.4
+      typescript: 5.5.3
+      webpack: 5.94.0
+
+  ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3):
+    dependencies:
+      '@cspotcode/source-map-support': 0.8.1
+      '@tsconfig/node10': 1.0.11
+      '@tsconfig/node12': 1.0.11
+      '@tsconfig/node14': 1.0.3
+      '@tsconfig/node16': 1.0.4
+      '@types/node': 20.14.10
+      acorn: 8.12.1
+      acorn-walk: 8.3.3
+      arg: 4.1.3
+      create-require: 1.1.1
+      diff: 4.0.2
+      make-error: 1.3.6
+      typescript: 5.5.3
+      v8-compile-cache-lib: 3.0.1
+      yn: 3.1.1
+
+  tsconfig-paths-webpack-plugin@4.1.0:
+    dependencies:
+      chalk: 4.1.2
+      enhanced-resolve: 5.17.0
+      tsconfig-paths: 4.2.0
+
+  tsconfig-paths@4.2.0:
+    dependencies:
+      json5: 2.2.3
+      minimist: 1.2.8
+      strip-bom: 3.0.0
+
+  tslib@2.6.3: {}
+
+  type-check@0.4.0:
+    dependencies:
+      prelude-ls: 1.2.1
+
+  type-detect@4.0.8: {}
+
+  type-fest@0.20.2: {}
+
+  type-fest@0.21.3: {}
+
+  type-is@1.6.18:
+    dependencies:
+      media-typer: 0.3.0
+      mime-types: 2.1.35
+
+  typedarray@0.0.6: {}
+
+  typescript@5.3.3: {}
+
+  typescript@5.5.3: {}
+
+  ua-parser-js@1.0.38: {}
+
+  uid-safe@2.1.5:
+    dependencies:
+      random-bytes: 1.0.0
+
+  uid@2.0.2:
+    dependencies:
+      '@lukeed/csprng': 1.1.0
+
+  undici-types@5.26.5: {}
+
+  universalify@2.0.1: {}
+
+  unpipe@1.0.0: {}
+
+  update-browserslist-db@1.1.0(browserslist@4.23.1):
+    dependencies:
+      browserslist: 4.23.1
+      escalade: 3.1.2
+      picocolors: 1.0.1
+
+  uri-js@4.4.1:
+    dependencies:
+      punycode: 2.3.1
+
+  util-deprecate@1.0.2: {}
+
+  utils-merge@1.0.1: {}
+
+  uuid@10.0.0: {}
+
+  v8-compile-cache-lib@3.0.1: {}
+
+  v8-to-istanbul@9.3.0:
+    dependencies:
+      '@jridgewell/trace-mapping': 0.3.25
+      '@types/istanbul-lib-coverage': 2.0.6
+      convert-source-map: 2.0.0
+
+  validator@13.12.0: {}
+
+  vary@1.1.2: {}
+
+  walker@1.0.8:
+    dependencies:
+      makeerror: 1.0.12
+
+  watchpack@2.4.1:
+    dependencies:
+      glob-to-regexp: 0.4.1
+      graceful-fs: 4.2.11
+
+  wcwidth@1.0.1:
+    dependencies:
+      defaults: 1.0.4
+
+  webidl-conversions@3.0.1: {}
+
+  webpack-node-externals@3.0.0: {}
+
+  webpack-sources@3.2.3: {}
+
+  webpack@5.92.1:
+    dependencies:
+      '@types/eslint-scope': 3.7.7
+      '@types/estree': 1.0.5
+      '@webassemblyjs/ast': 1.12.1
+      '@webassemblyjs/wasm-edit': 1.12.1
+      '@webassemblyjs/wasm-parser': 1.12.1
+      acorn: 8.12.1
+      acorn-import-attributes: 1.9.5(acorn@8.12.1)
+      browserslist: 4.23.1
+      chrome-trace-event: 1.0.4
+      enhanced-resolve: 5.17.0
+      es-module-lexer: 1.5.4
+      eslint-scope: 5.1.1
+      events: 3.3.0
+      glob-to-regexp: 0.4.1
+      graceful-fs: 4.2.11
+      json-parse-even-better-errors: 2.3.1
+      loader-runner: 4.3.0
+      mime-types: 2.1.35
+      neo-async: 2.6.2
+      schema-utils: 3.3.0
+      tapable: 2.2.1
+      terser-webpack-plugin: 5.3.10(webpack@5.92.1)
+      watchpack: 2.4.1
+      webpack-sources: 3.2.3
+    transitivePeerDependencies:
+      - '@swc/core'
+      - esbuild
+      - uglify-js
+
+  webpack@5.94.0:
+    dependencies:
+      '@types/estree': 1.0.5
+      '@webassemblyjs/ast': 1.12.1
+      '@webassemblyjs/wasm-edit': 1.12.1
+      '@webassemblyjs/wasm-parser': 1.12.1
+      acorn: 8.12.1
+      acorn-import-attributes: 1.9.5(acorn@8.12.1)
+      browserslist: 4.23.1
+      chrome-trace-event: 1.0.4
+      enhanced-resolve: 5.17.1
+      es-module-lexer: 1.5.4
+      eslint-scope: 5.1.1
+      events: 3.3.0
+      glob-to-regexp: 0.4.1
+      graceful-fs: 4.2.11
+      json-parse-even-better-errors: 2.3.1
+      loader-runner: 4.3.0
+      mime-types: 2.1.35
+      neo-async: 2.6.2
+      schema-utils: 3.3.0
+      tapable: 2.2.1
+      terser-webpack-plugin: 5.3.10(webpack@5.94.0)
+      watchpack: 2.4.1
+      webpack-sources: 3.2.3
+    transitivePeerDependencies:
+      - '@swc/core'
+      - esbuild
+      - uglify-js
+
+  whatwg-url@5.0.0:
+    dependencies:
+      tr46: 0.0.3
+      webidl-conversions: 3.0.1
+
+  which@2.0.2:
+    dependencies:
+      isexe: 2.0.0
+
+  winston-daily-rotate-file@5.0.0(winston@3.14.2):
+    dependencies:
+      file-stream-rotator: 0.6.1
+      object-hash: 3.0.0
+      triple-beam: 1.4.1
+      winston: 3.14.2
+      winston-transport: 4.7.1
+
+  winston-transport@4.7.1:
+    dependencies:
+      logform: 2.6.1
+      readable-stream: 3.6.2
+      triple-beam: 1.4.1
+
+  winston@3.14.2:
+    dependencies:
+      '@colors/colors': 1.6.0
+      '@dabh/diagnostics': 2.0.3
+      async: 3.2.6
+      is-stream: 2.0.1
+      logform: 2.6.1
+      one-time: 1.0.0
+      readable-stream: 3.6.2
+      safe-stable-stringify: 2.5.0
+      stack-trace: 0.0.10
+      triple-beam: 1.4.1
+      winston-transport: 4.7.1
+
+  wmf@1.0.2: {}
+
+  word-wrap@1.2.5: {}
+
+  word@0.3.0: {}
+
+  wrap-ansi@6.2.0:
+    dependencies:
+      ansi-styles: 4.3.0
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+
+  wrap-ansi@7.0.0:
+    dependencies:
+      ansi-styles: 4.3.0
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+
+  wrap-ansi@8.1.0:
+    dependencies:
+      ansi-styles: 6.2.1
+      string-width: 5.1.2
+      strip-ansi: 7.1.0
+
+  wrappy@1.0.2: {}
+
+  write-file-atomic@4.0.2:
+    dependencies:
+      imurmurhash: 0.1.4
+      signal-exit: 3.0.7
+
+  xlsx@0.18.5:
+    dependencies:
+      adler-32: 1.3.1
+      cfb: 1.2.2
+      codepage: 1.15.0
+      crc-32: 1.2.2
+      ssf: 0.11.2
+      wmf: 1.0.2
+      word: 0.3.0
+
+  xtend@4.0.2: {}
+
+  y18n@5.0.8: {}
+
+  yallist@3.1.1: {}
+
+  yargs-parser@21.1.1: {}
+
+  yargs@17.7.2:
+    dependencies:
+      cliui: 8.0.1
+      escalade: 3.1.2
+      get-caller-file: 2.0.5
+      require-directory: 2.1.1
+      string-width: 4.2.3
+      y18n: 5.0.8
+      yargs-parser: 21.1.1
+
+  yn@3.1.1: {}
+
+  yocto-queue@0.1.0: {}

+ 8 - 0
server/pnpm-workspace.yaml

@@ -0,0 +1,8 @@
+ignoredBuiltDependencies:
+  - bcrypt
+
+onlyBuiltDependencies:
+  - '@nestjs/core'
+  - '@prisma/client'
+  - '@prisma/engines'
+  - prisma

+ 242 - 0
server/prisma/migrations/20241031011215_init/migration.sql

@@ -0,0 +1,242 @@
+-- CreateEnum
+CREATE TYPE "Status" AS ENUM ('ACTIVE', 'INACTIVE');
+
+-- CreateEnum
+CREATE TYPE "Sex" AS ENUM ('FEMALE', 'MALE');
+
+-- CreateEnum
+CREATE TYPE "MenuType" AS ENUM ('DIRECTORY', 'MENU', 'BUTTON');
+
+-- CreateEnum
+CREATE TYPE "Method" AS ENUM ('GET', 'POST', 'PUT', 'PATCH', 'DELETE');
+
+-- CreateTable
+CREATE TABLE "Role" (
+    "id" TEXT NOT NULL,
+    "name" TEXT NOT NULL,
+    "code" TEXT NOT NULL,
+    "description" TEXT,
+    "sort" INTEGER NOT NULL,
+    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updatedAt" TIMESTAMP(3) NOT NULL,
+
+    CONSTRAINT "Role_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "Menu" (
+    "id" TEXT NOT NULL,
+    "title" TEXT NOT NULL,
+    "type" "MenuType" NOT NULL DEFAULT 'MENU',
+    "parentId" TEXT,
+    "name" TEXT,
+    "path" TEXT,
+    "component" TEXT,
+    "meta" JSONB,
+    "props" JSONB,
+    "sort" INTEGER NOT NULL,
+    "permission" TEXT,
+    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updatedAt" TIMESTAMP(3) NOT NULL,
+
+    CONSTRAINT "Menu_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "Permission" (
+    "id" TEXT NOT NULL,
+    "roleId" TEXT NOT NULL,
+    "menuId" TEXT NOT NULL,
+    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+    CONSTRAINT "Permission_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "Organization" (
+    "id" TEXT NOT NULL,
+    "name" TEXT NOT NULL,
+    "code" TEXT NOT NULL,
+    "parentId" TEXT,
+    "sort" INTEGER NOT NULL,
+    "description" TEXT,
+    "icon" TEXT,
+    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updatedAt" TIMESTAMP(3) NOT NULL,
+
+    CONSTRAINT "Organization_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "Post" (
+    "id" TEXT NOT NULL,
+    "name" TEXT NOT NULL,
+    "orgId" TEXT NOT NULL,
+    "parentId" TEXT,
+    "sort" INTEGER NOT NULL,
+    "description" TEXT,
+    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updatedAt" TIMESTAMP(3) NOT NULL,
+
+    CONSTRAINT "Post_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "User" (
+    "id" TEXT NOT NULL,
+    "userName" TEXT NOT NULL,
+    "password" TEXT NOT NULL,
+    "cnName" TEXT NOT NULL,
+    "email" TEXT NOT NULL,
+    "phone" TEXT NOT NULL,
+    "avatar" TEXT NOT NULL,
+    "sex" "Sex" NOT NULL DEFAULT 'FEMALE',
+    "status" "Status" NOT NULL DEFAULT 'ACTIVE',
+    "sort" INTEGER NOT NULL,
+    "token" TEXT,
+    "tags" TEXT[] DEFAULT ARRAY[]::TEXT[],
+    "city" TEXT[] DEFAULT ARRAY[]::TEXT[],
+    "address" TEXT,
+    "roleId" TEXT NOT NULL,
+    "orgId" TEXT NOT NULL,
+    "postId" TEXT NOT NULL,
+    "loginCount" INTEGER NOT NULL DEFAULT 0,
+    "lastIp" TEXT,
+    "lastLoginAt" TIMESTAMP(3),
+    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updatedAt" TIMESTAMP(3) NOT NULL,
+
+    CONSTRAINT "User_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "Log" (
+    "id" TEXT NOT NULL,
+    "userId" TEXT NOT NULL,
+    "ip" TEXT NOT NULL,
+    "action" TEXT NOT NULL,
+    "method" "Method" NOT NULL,
+    "params" JSONB NOT NULL,
+    "os" TEXT NOT NULL,
+    "browser" TEXT NOT NULL,
+    "province" TEXT,
+    "city" TEXT,
+    "adcode" TEXT,
+    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+    CONSTRAINT "Log_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "Message" (
+    "id" TEXT NOT NULL,
+    "title" TEXT NOT NULL,
+    "content" TEXT NOT NULL,
+    "status" "Status" NOT NULL DEFAULT 'ACTIVE',
+    "pinned" BOOLEAN NOT NULL DEFAULT false,
+    "userId" TEXT NOT NULL,
+    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updatedAt" TIMESTAMP(3) NOT NULL,
+
+    CONSTRAINT "Message_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "MessageRead" (
+    "id" TEXT NOT NULL,
+    "messageId" TEXT NOT NULL,
+    "userId" TEXT NOT NULL,
+    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+    CONSTRAINT "MessageRead_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "Internalization" (
+    "id" TEXT NOT NULL,
+    "name" TEXT NOT NULL,
+    "parentId" TEXT,
+    "zhCN" TEXT,
+    "enUS" TEXT,
+    "jaJP" TEXT,
+    "zhTW" TEXT,
+    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updatedAt" TIMESTAMP(3) NOT NULL,
+
+    CONSTRAINT "Internalization_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Role_name_key" ON "Role"("name");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Role_code_key" ON "Role"("code");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Menu_name_key" ON "Menu"("name");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Menu_path_key" ON "Menu"("path");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Menu_permission_key" ON "Menu"("permission");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Organization_name_key" ON "Organization"("name");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Organization_code_key" ON "Organization"("code");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Post_name_key" ON "Post"("name");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "User_userName_key" ON "User"("userName");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "User_phone_key" ON "User"("phone");
+
+-- AddForeignKey
+ALTER TABLE "Menu" ADD CONSTRAINT "Menu_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "Menu"("id") ON DELETE SET NULL ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "Permission" ADD CONSTRAINT "Permission_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "Role"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "Permission" ADD CONSTRAINT "Permission_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "Organization" ADD CONSTRAINT "Organization_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "Organization"("id") ON DELETE SET NULL ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "Post" ADD CONSTRAINT "Post_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "Post" ADD CONSTRAINT "Post_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "Post"("id") ON DELETE SET NULL ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "User" ADD CONSTRAINT "User_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "Role"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "User" ADD CONSTRAINT "User_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "User" ADD CONSTRAINT "User_postId_fkey" FOREIGN KEY ("postId") REFERENCES "Post"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "Log" ADD CONSTRAINT "Log_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "Message" ADD CONSTRAINT "Message_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "MessageRead" ADD CONSTRAINT "MessageRead_messageId_fkey" FOREIGN KEY ("messageId") REFERENCES "Message"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "MessageRead" ADD CONSTRAINT "MessageRead_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "Internalization" ADD CONSTRAINT "Internalization_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "Internalization"("id") ON DELETE SET NULL ON UPDATE CASCADE;

+ 29 - 0
server/prisma/migrations/20250802123530_add_product_model/migration.sql

@@ -0,0 +1,29 @@
+-- CreateTable
+CREATE TABLE "ActivationCode" (
+    "id" SERIAL NOT NULL,
+    "code" TEXT NOT NULL,
+    "type" TEXT NOT NULL,
+    "importedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "activated" BOOLEAN NOT NULL DEFAULT false,
+    "activatedAt" TIMESTAMP(3),
+    "refunded" BOOLEAN NOT NULL DEFAULT false,
+    "refundedAt" TIMESTAMP(3),
+    "refundNote" TEXT,
+    "revoked" BOOLEAN NOT NULL DEFAULT false,
+    "revokedAt" TIMESTAMP(3),
+    "dataDate" TIMESTAMP(3) NOT NULL,
+
+    CONSTRAINT "ActivationCode_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "ActivationCode_code_key" ON "ActivationCode"("code");
+
+-- CreateIndex
+CREATE INDEX "ActivationCode_type_idx" ON "ActivationCode"("type");
+
+-- CreateIndex
+CREATE INDEX "ActivationCode_dataDate_idx" ON "ActivationCode"("dataDate");
+
+-- CreateIndex
+CREATE INDEX "ActivationCode_activated_refunded_revoked_idx" ON "ActivationCode"("activated", "refunded", "revoked");

+ 3 - 0
server/prisma/migrations/migration_lock.toml

@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (i.e. Git)
+provider = "postgresql"

+ 238 - 0
server/prisma/schema.prisma

@@ -0,0 +1,238 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
+// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
+
+generator client {
+  provider = "prisma-client-js"
+}
+
+datasource db {
+  provider = "postgresql"
+  url      = env("DATABASE_URL")
+}
+
+// User - status
+enum Status {
+  ACTIVE
+  INACTIVE
+}
+
+// User - sex
+enum Sex {
+  FEMALE
+  MALE
+}
+
+// Menu - type
+enum MenuType {
+  DIRECTORY
+  MENU
+  BUTTON
+}
+
+// Log - method
+enum Method {
+  GET
+  POST
+  PUT
+  PATCH
+  DELETE
+}
+
+// 系统管理 - 角色管理
+model Role {
+  id            String          @id @default(uuid()) // 主键
+  name          String          @unique // 角色名称
+  code          String          @unique // 角色编码
+  description   String?         // 角色描述
+  sort          Int             // 排序
+  permissions   Permission[]    // 与Permission的一对多关系
+  createdAt     DateTime        @default(now()) // 创建时间
+  updatedAt     DateTime        @updatedAt // 更新时间
+  users         User[]          // 关联用户
+}
+
+// 系统管理 - 菜单管理
+model Menu {
+  id            String          @id @default(uuid()) // 主键
+  title         String          // 菜单名称
+  type          MenuType        @default(MENU) // 菜单类型
+  parentId      String?  
+  parent        Menu?           @relation(name: "MenuHierarchy", fields: [parentId], references: [id])
+  name          String?          @unique // 路由名称
+  path          String?          @unique // 路由地址
+  component     String?          // 组件路径
+  meta          Json?            // 路由元信息(JSON 对象)
+  props         Json?            // Iframe 页面参数(JSON 对象)
+  sort          Int             // 排序
+  permission    String?         @unique // 权限标识
+  permissions   Permission[]    // 与Permission的一对多关系
+  createdAt     DateTime        @default(now()) // 创建时间
+  updatedAt     DateTime        @updatedAt // 更新时间
+  children      Menu[]          @relation(name: "MenuHierarchy")
+}
+
+// 系统管理 - 权限管理
+model Permission {
+  id            String          @id @default(uuid()) // 主键
+  roleId        String          // 角色ID
+  menuId        String          // 菜单ID
+  createdAt     DateTime        @default(now()) // 创建时间
+  role          Role            @relation(fields: [roleId], references: [id]) // 与Role的关联
+  menu          Menu            @relation(fields: [menuId], references: [id]) // 与Menu的关联
+}
+
+// 智能行政 - 组织管理
+model Organization {
+  id            String          @id @default(uuid()) // 主键
+  name          String          @unique // 组织名称
+  code          String          @unique // 组织编码
+  parentId      String?  
+  parent        Organization?   @relation(name: "OrgHierarchy", fields: [parentId], references: [id])
+  // users         User[]          // 关联用户
+  sort          Int             // 排序
+  description   String?         // 组织描述
+  icon          String?         // 组织图标
+  posts         Post[]          // 岗位
+  createdAt     DateTime        @default(now()) // 创建时间
+  updatedAt     DateTime        @updatedAt // 更新时间
+  children      Organization[]  @relation(name: "OrgHierarchy")
+}
+
+// 智能行政 - 岗位管理
+model Post {
+  id            String          @id @default(uuid()) // 主键
+  name          String          @unique // 岗位名称
+  orgId         String          // 关联的组织 id
+  organization  Organization    @relation(fields: [orgId], references: [id])   
+  parentId      String?    
+  parent        Post?           @relation(name: "PostHierarchy", fields: [parentId], references: [id])
+  // users         User[]          // 关联用户
+  sort          Int             // 排序
+  description   String?         // 岗位描述
+  createdAt     DateTime        @default(now()) // 创建时间
+  updatedAt     DateTime        @updatedAt // 更新时间
+  children      Post[]          @relation(name: "PostHierarchy")
+}
+
+// 系统管理 - 用户管理
+model User {
+  id            String          @id @default(uuid()) // 主键
+  userName      String          @unique // 用户名
+  password      String          // 密码
+  cnName        String          // 中文名
+  email         String          @unique // 电子邮箱
+  phone         String          @unique // 手机号
+  avatar        String          // 头像
+  sex           Sex             @default(FEMALE) // 性别
+  status        Status          @default(ACTIVE) // 状态
+  sort          Int             // 排序
+  token         String?         // token
+  tags          String[]        @default([]) // 标签
+  city          String[]        @default([]) // 城市
+  address       String?         // 详细地址
+  roleId        String          // 关联的角色 id
+  role          Role            @relation(fields: [roleId], references: [id])
+  // orgId         String          // 关联的组织 id
+  // organization  Organization    @relation(fields: [orgId], references: [id])
+  // postId        String          // 关联的岗位 id
+  // post          Post            @relation(fields: [postId], references: [id])
+  logs          Log[]           // 操作日志
+  loginCount    Int             @default(0) // 登录次数
+  lastIp        String?         // 最后登录ip
+  lastLoginAt   DateTime?       // 最后登录时间
+  messages      Message[]       // 该用户发布的消息列表
+  messageReads  MessageRead[]   // 关联已读列表
+  createdAt     DateTime        @default(now()) // 创建时间
+  updatedAt     DateTime        @updatedAt // 更新时间
+}
+
+// 系统管理 - 操作日志
+model Log {
+  id            String          @id @default(uuid()) // 主键
+  userId        String          // 关联的用户 id
+  user          User            @relation(fields: [userId], references: [id])
+  ip            String          // ip
+  action        String          // 请求地址
+  method        Method          // 请求方法
+  params        Json            // 请求参数(JSON 对象)
+  os            String          // 系统
+  browser       String          // 浏览器
+  province      String?         // 所在省份
+  city          String?         // 所在城市
+  adcode        String?         // 城市编码
+  createdAt     DateTime        @default(now()) // 创建时间
+}
+
+// 智能行政 - 消息公告
+model Message {
+  id            String          @id @default(uuid()) // 主键
+  title         String          // 标题
+  content       String          // 内容
+  status        Status          @default(ACTIVE) // 状态
+  pinned        Boolean         @default(false)
+  userId        String          // 作者 id
+  user          User            @relation(fields: [userId], references: [id])
+  messageReads  MessageRead[]   // 关联已读列表
+  createdAt     DateTime        @default(now()) // 创建时间
+  updatedAt     DateTime        @updatedAt // 更新时间
+}
+
+// 智能行政 - 消息公告 - 已读列表
+model MessageRead {
+  id            String          @id @default(uuid()) // 主键
+  messageId     String          // 消息 id
+  message       Message         @relation(fields: [messageId], references: [id])
+  userId        String          // 用户 id
+  user          User            @relation(fields: [userId], references: [id])
+  createdAt     DateTime        @default(now()) // 创建时间
+}
+
+// 系统管理 - 国际化
+model Internalization {
+  id            String          @id @default(uuid()) // 主键
+  name          String          // 键
+  parentId      String?  
+  parent        Internalization?       @relation(name: "InternalizationHierarchy", fields: [parentId], references: [id])
+  zhCN          String?         // 中文
+  enUS          String?         // 英文
+  jaJP          String?         // 日文
+  zhTW          String?         // 繁体中文
+  createdAt     DateTime        @default(now()) // 创建时间
+  updatedAt     DateTime        @updatedAt // 更新时间
+  children      Internalization[]      @relation(name: "InternalizationHierarchy")
+}
+
+// 激活码管理
+
+model ActivationCode {
+  id           Int                @id @default(autoincrement()) // 自增主键ID
+  code         String             @unique                       // 激活码唯一字符串
+  type         Int                                              // 原激活码类型
+  typeId       String?                                          // 新激活码类型id
+  codeType     ActivationCodeType? @relation(fields: [typeId], references: [id]) // 关联激活码类型
+  importedAt   DateTime           @default(now())               // 导入时间
+  activated    Boolean            @default(false)               // 是否已激活
+  activatedAt  DateTime?                                        // 激活时间(可为空)
+  refunded     Boolean            @default(false)               // 是否已退款
+  refundedAt   DateTime?                                        // 退款时间(可为空)
+  refundNote   String?                                          // 退款备注(例如原因)
+  revoked      Boolean            @default(false)               // 是否已收回
+  revokedAt    DateTime?                                        // 收回时间(可为空)
+  dataDate     DateTime?                                        // 数据日期,用于数据归属时间
+
+  @@index([type])
+  @@index([dataDate])
+  @@index([activated, refunded, revoked])
+}
+
+model ActivationCodeType {
+  id              String           @id @default(uuid()) // 主键
+  name            String           @unique // 类型名称(添加唯一约束)
+  activationCodes ActivationCode[] // 反向关联激活码
+  createdAt       DateTime         @default(now()) // 创建时间
+  updatedAt       DateTime         @updatedAt // 更新时间
+}
+

+ 56 - 0
server/src/app.module.ts

@@ -0,0 +1,56 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-12 14:34:56
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-09-09 09:57:27
+ * @Description: AppModule
+ */
+import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
+import { EventEmitterModule } from '@nestjs/event-emitter';
+import { WinstonModule } from 'nest-winston';
+
+import { LoggerMiddleware } from '@/middleware/logger.middleware'; // 全局日志中间件
+import { MessageModule } from '@/modules/administrative/message/message.module'; // 智能行政 - 消息公告
+import { OrganazationModule } from '@/modules/administrative/organazation/organazation.module'; // 智能行政-组织管理
+import { PostManageModule } from '@/modules/administrative/post-manage/post-manage.module'; // 智能行政-岗位管理
+import { AuthModule } from '@/modules/auth/auth.module'; // 登录授权
+import { FileUploadModule } from '@/modules/file-upload/file-upload.module'; // 文件上传
+import { InternalizationModule } from '@/modules/system-manage/internalization/internalization.module'; // 系统管理 - 国际化
+import { MenuManageModule } from '@/modules/system-manage/menu-manage/menu-manage.module'; // 系统管理 - 菜单管理
+import { OperationLogModule } from '@/modules/system-manage/operation-log/operation-log.module'; // 系统管理 - 操作日志
+import { RoleManageModule } from '@/modules/system-manage/role-manage/role-manage.module'; // 系统管理 - 角色管理
+import { UserManageModule } from '@/modules/system-manage/user-manage/user-manage.module'; // 系统管理 - 用户管理
+
+import winstonLogger from './config/winston.config';
+import { ActivationCodeModule } from './modules/activation-code/activation-code.module';
+import { CodeTypeModule } from './modules/code-type/code-type.module';
+
+@Module({
+  imports: [
+    OrganazationModule,
+    PostManageModule,
+    AuthModule,
+    UserManageModule,
+    FileUploadModule,
+    OperationLogModule,
+    InternalizationModule,
+    MenuManageModule,
+    RoleManageModule,
+    MessageModule,
+    WinstonModule.forRoot({
+      transports: winstonLogger.transports,
+      format: winstonLogger.format,
+      defaultMeta: winstonLogger.defaultMeta,
+      exitOnError: false, // 防止意外退出
+    }),
+    // 发布-订阅模块
+    EventEmitterModule.forRoot(),
+    ActivationCodeModule,
+    CodeTypeModule,
+  ],
+})
+export class AppModule implements NestModule {
+  configure(consumer: MiddlewareConsumer) {
+    consumer.apply(LoggerMiddleware).forRoutes('*');
+  }
+}

+ 68 - 0
server/src/config/winston.config.ts

@@ -0,0 +1,68 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-08-29 16:41:59
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-30 11:28:50
+ * @Description: winston 日志
+ */
+import chalk from 'chalk'; // 用于颜色化输出
+import { createLogger, format, transports } from 'winston';
+import DailyRotateFile from 'winston-daily-rotate-file';
+
+// 定义日志级别颜色
+const levelsColors = {
+  error: 'red',
+  warn: 'yellow',
+  info: 'green',
+  debug: 'blue',
+  verbose: 'cyan',
+};
+
+const winstonLogger = createLogger({
+  format: format.combine(format.timestamp(), format.errors({ stack: true }), format.splat(), format.json()),
+  defaultMeta: { service: 'log-service' },
+  transports: [
+    new DailyRotateFile({
+      filename: 'logs/errors/error-%DATE%.log', // 日志名称,占位符 %DATE% 取值为 datePattern 值。
+      datePattern: 'YYYY-MM-DD', // 日志轮换的频率,此处表示每天。
+      zippedArchive: true, // 是否通过压缩的方式归档被轮换的日志文件。
+      maxSize: '20m', // 设置日志文件的最大大小,m 表示 mb 。
+      maxFiles: '14d', // 保留日志文件的最大天数,此处表示自动删除超过 14 天的日志文件。
+      level: 'error', // 日志类型,此处表示只记录错误日志。
+    }),
+    new DailyRotateFile({
+      filename: 'logs/warnings/warning-%DATE%.log',
+      datePattern: 'YYYY-MM-DD',
+      zippedArchive: true,
+      maxSize: '20m',
+      maxFiles: '14d',
+      level: 'warn',
+    }),
+    new DailyRotateFile({
+      filename: 'logs/app/app-%DATE%.log',
+      datePattern: 'YYYY-MM-DD',
+      zippedArchive: true,
+      maxSize: '20m',
+      maxFiles: '14d',
+    }),
+    new transports.Console({
+      format: format.combine(
+        format.colorize({
+          colors: levelsColors,
+        }),
+        format.simple(),
+        format.printf((info) => {
+          // 直接使用 info.level 获取日志级别,避免使用 symbol 作为索引
+          const level = info.level as keyof typeof levelsColors;
+          const color = levelsColors[level] || 'white';
+          const chalkColor = chalk[color] || ((text: string) => text);
+          const message = `${chalkColor(info.timestamp)} ${chalkColor(level)}: ${info.message}`;
+          return message;
+        }),
+      ),
+      level: 'debug',
+    }),
+  ],
+});
+
+export default winstonLogger;

+ 34 - 0
server/src/dto/params.dto.ts

@@ -0,0 +1,34 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-11 16:39:34
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-07-22 10:19:30
+ * @Description: 公共参数
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { Transform } from 'class-transformer';
+import { IsInt, IsNotEmpty, Min } from 'class-validator';
+
+export class PaginatingDTO {
+  @ApiProperty({
+    type: Number,
+    description: '当前页码',
+    default: 1,
+  })
+  @IsInt({ message: 'current 参数只能是 number 类型' })
+  @Min(1, { message: 'current 参数不能小于 1' })
+  @IsNotEmpty({ message: '缺少 current 页码参数' })
+  @Transform(({ value }) => parseInt(value, 10))
+  current: number;
+
+  @ApiProperty({
+    type: Number,
+    description: '当前页条数',
+    default: 10,
+  })
+  @IsInt({ message: 'size 参数只能是 number 类型' })
+  @Min(1, { message: 'size 参数不能小于 1' })
+  @IsNotEmpty({ message: '缺少 size 页码参数' })
+  @Transform(({ value }) => parseInt(value, 10))
+  size: number;
+}

+ 32 - 0
server/src/dto/response.dto.ts

@@ -0,0 +1,32 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-10 14:05:23
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-07-11 16:26:16
+ * @Description: 全局响应体
+ */
+import { ApiProperty } from '@nestjs/swagger';
+
+import { RESPONSE_CODE, RESPONSE_MSG } from '@/enums';
+
+export class ResponseDto {
+  @ApiProperty({
+    type: Number,
+    description: '业务状态码',
+    default: RESPONSE_CODE.SUCCESS,
+  })
+  code: number;
+
+  @ApiProperty({
+    type: String,
+    description: '业务信息',
+    default: RESPONSE_MSG.SUCCESS,
+  })
+  msg: string;
+
+  @ApiProperty({ description: '业务数据' })
+  data?: any;
+
+  @ApiProperty({ type: Number, description: '时间戳', default: 1720685424078 })
+  timestamp: number;
+}

+ 38 - 0
server/src/enums/index.ts

@@ -0,0 +1,38 @@
+/**
+ * @description: 响应码
+ */
+export enum RESPONSE_CODE {
+  NOSUCCESS = -1, // 表示请求成功,但操作未成功
+  SUCCESS = 200, // 请求成功
+  BAD_REQUEST = 400, // 请求错误
+  UNAUTHORIZED = 401, // 未授权
+  FORBIDDEN = 403, // 禁止访问
+  NOT_FOUND = 404, // 资源未找到
+  INTERNAL_SERVER_ERROR = 500, // 服务器错误
+}
+
+/**
+ * @description: 请求提示语
+ */
+export enum RESPONSE_MSG {
+  SUCCESS = '请求成功',
+  FAILURE = '请求失败',
+  ERROR = '服务器错误',
+}
+
+/**
+ * @description: 国际化语言
+ */
+export enum LOCALES {
+  zhCN = 'zh-CN', // 中文
+  enUS = 'en-US', // 英文
+  jaJP = 'ja-JP', // 日文
+  zhTW = 'zh-TW', // 繁体中文
+}
+
+/**
+ * @description: 服务器推送事件
+ */
+export enum EVENTBUS_TYPE {
+  MESSAGE_CREATE = 'message_create', // 消息创建
+}

+ 26 - 0
server/src/filter/all-exception.filter.ts

@@ -0,0 +1,26 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-10 14:17:49
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-02 09:41:51
+ * @Description: 全局异常过滤器
+ */
+import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus } from '@nestjs/common';
+import { Response } from 'express';
+
+import { responseMessage } from '@/utils';
+
+// @Catch() 装饰器绑定所需的元数据到异常过滤器上。它告诉 Nest这个特定的过滤器正在寻找
+@Catch()
+export class AllExceptionsFilter implements ExceptionFilter {
+  catch(exception: HttpException, host: ArgumentsHost) {
+    // 获取上下文
+    const ctx = host.switchToHttp();
+    // 获取响应体
+    const response = ctx.getResponse<Response>();
+    // 获取状态码,判断是HTTP异常还是服务器异常
+    const statusCode = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR;
+    // 自定义异常返回体
+    response.status(statusCode).json(responseMessage(null, exception.message, statusCode));
+  }
+}

+ 27 - 0
server/src/filter/http-exception.filter.ts

@@ -0,0 +1,27 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-10 14:17:49
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-07-10 15:48:42
+ * @Description: http 异常过滤器
+ */
+import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from '@nestjs/common';
+import { Response } from 'express';
+
+import { responseMessage } from '@/utils';
+
+// @Catch() 装饰器绑定所需的元数据到异常过滤器上。它告诉 Nest这个特定的过滤器正在寻找
+@Catch(HttpException)
+export class HttpExceptionsFilter implements ExceptionFilter {
+  catch(exception: HttpException, host: ArgumentsHost) {
+    // 获取上下文
+    const ctx = host.switchToHttp();
+    // 获取响应体
+    const response = ctx.getResponse<Response>();
+    // 获取状态码
+    const statusCode = exception.getStatus();
+
+    // 自定义异常返回体
+    response.status(statusCode).json(responseMessage(null, exception.message, statusCode));
+  }
+}

+ 22 - 0
server/src/interceptor/logger.interceptor.ts

@@ -0,0 +1,22 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-08-07 09:48:27
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-07 10:16:31
+ * @Description: LoggerInterceptor 日志拦截器
+ */
+import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
+import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
+
+import { OperationLogService } from '@/modules/system-manage/operation-log/operation-log.service';
+
+@Injectable()
+export class LoggerInterceptor implements NestInterceptor {
+  constructor(private readonly operationLogService: OperationLogService) {}
+
+  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
+    this.operationLogService.logAction();
+    return next.handle().pipe(map((data) => data));
+  }
+}

+ 75 - 0
server/src/main.ts

@@ -0,0 +1,75 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-09 15:26:41
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-10-09 10:44:10
+ * @Description: 全局入口文件
+ */
+declare const module: any;
+import { NestFactory } from '@nestjs/core';
+import { NestExpressApplication } from '@nestjs/platform-express';
+import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
+import express from 'express';
+import session from 'express-session';
+import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';
+import { join } from 'path';
+
+import { AllExceptionsFilter } from '@/filter/all-exception.filter'; // 全局异常过滤器
+import { HttpExceptionsFilter } from '@/filter/http-exception.filter'; // http 异常过滤器
+import { requestMiddleware } from '@/middleware/request.middleware'; // 全局请求拦截中间件
+import { ValidationPipe } from '@/pipe/validation.pipe'; // 参数校验
+
+import { AppModule } from './app.module';
+async function bootstrap() {
+  const app = await NestFactory.create<NestExpressApplication>(AppModule);
+
+  app.use(express.json()); // 用于解析 JSON 格式的请求体
+  app.use(express.urlencoded({ extended: true })); // 用于解析 URL 编码格式的请求体
+
+  // 替换日志器
+  app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER));
+
+  // 设置信任代理
+  app.set('trust proxy', true);
+
+  // 错误异常捕获 和 过滤处理
+  app.useGlobalFilters(new AllExceptionsFilter());
+  app.useGlobalFilters(new HttpExceptionsFilter());
+
+  // 全局参数校验
+  app.useGlobalPipes(new ValidationPipe());
+
+  // 全局请求拦截中间件
+  // app.use(requestMiddleware);
+
+  // 启动热重载
+  if (module.hot) {
+    module.hot.accept();
+    module.hot.dispose(() => app.close());
+  }
+
+  // 配置 session
+  app.use(
+    session({
+      secret: 'baiwumm', // 签名
+      resave: false, // 强制保存 sseion 即使它并没有变化,默认为true
+      saveUninitialized: false, // 强制将未初始化的 session 存储
+    }),
+  );
+
+  // 配置文件访问  文件夹为静态目录,以达到可直接访问下面文件的目的
+  const rootDir = join(__dirname, '..');
+  app.use('/static', express.static(join(rootDir, '/upload')));
+
+  // 构建swagger文档
+  const options = new DocumentBuilder()
+    .setTitle('Vue3 Admin 接口文档')
+    .setDescription('真正的大师永远怀着一颗学徒的心!')
+    .setVersion('1.0')
+    .build();
+  const document = SwaggerModule.createDocument(app, options);
+  SwaggerModule.setup('docs', app, document);
+
+  await app.listen(3000);
+}
+bootstrap();

+ 45 - 0
server/src/middleware/logger.middleware.ts

@@ -0,0 +1,45 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-08-29 17:45:48
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-30 13:45:56
+ * @Description: 全局日志中间件
+ */
+import { Injectable, Logger, NestMiddleware } from '@nestjs/common';
+import dayjs from 'dayjs';
+import { NextFunction, Request, Response } from 'express';
+
+@Injectable()
+export class LoggerMiddleware implements NestMiddleware {
+  private logger = new Logger();
+  use(req: Request, res: Response, next: NextFunction) {
+    // 记录开始时间
+    const start = Date.now();
+    // 获取请求信息
+    const { method, originalUrl, ip, httpVersion, headers } = req;
+
+    // 获取响应信息
+    const { statusCode } = res;
+
+    res.on('finish', () => {
+      // 记录结束时间
+      const end = Date.now();
+      // 计算时间差
+      const duration = end - start;
+
+      // 组装日志信息:[timestamp] [method] [url] HTTP/[httpVersion] [client IP] [status code] [response time]ms [user-agent]
+      const logFormat = `${dayjs().valueOf()} ${method} ${originalUrl} HTTP/${httpVersion} ${ip} ${statusCode} ${duration}ms ${headers['user-agent']}`;
+
+      // 根据状态码,进行日志类型区分
+      if (statusCode >= 500) {
+        this.logger.error(logFormat, originalUrl);
+      } else if (statusCode >= 400) {
+        this.logger.warn(logFormat, originalUrl);
+      } else {
+        this.logger.log(logFormat, originalUrl);
+      }
+    });
+
+    next();
+  }
+}

+ 23 - 0
server/src/middleware/request.middleware.ts

@@ -0,0 +1,23 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-09-29 17:55:42
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-10-09 10:19:48
+ * @Description: 全局请求拦截中间件
+ */
+import { NextFunction, Request, Response } from 'express';
+
+import { responseMessage } from '@/utils';
+export function requestMiddleware(req: Request, res: Response, next: NextFunction) {
+  if (
+    req.method === 'GET' ||
+    req.url.includes('/auth/login') ||
+    req.url.includes('/auth/logout') ||
+    req.url.includes('/auth/juejin') ||
+    req.url.includes('/common/')
+  ) {
+    next();
+  } else {
+    res.send(responseMessage(null, '演示系统,禁止操作!', -1));
+  }
+}

+ 141 - 0
server/src/modules/activation-code/activation-code.controller.ts

@@ -0,0 +1,141 @@
+/*
+ * @Description: ActivationCodeController - 激活码管理
+ */
+import {
+  Body,
+  Controller,
+  Delete,
+  Get,
+  Param,
+  ParseIntPipe,
+  Patch,
+  Post,
+  Put,
+  Query,
+  UseGuards,
+  UseInterceptors,
+} from '@nestjs/common';
+import { AuthGuard } from '@nestjs/passport';
+import { ApiBearerAuth, ApiHeader, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger';
+
+import { LoggerInterceptor } from '@/interceptor/logger.interceptor';
+
+import { ActivationCodeService } from './activation-code.service';
+import { BatchImportActivationCodeArrayDto } from './dto/batch-import-activation-code.dto';
+import { ExportActivationCodeDto } from './dto/export-activation-code.dto';
+import { ActivationCodeParamsDto } from './dto/params-activation-code.dto';
+import { RefundActivationCodeDto } from './dto/refund-activation-code.dto';
+import { ResponseActivationCodeDto, ResponseSaveActivationCodeDto } from './dto/response-activation-code.dto';
+import { SaveActivationCodeDto } from './dto/save-activation-code.dto';
+
+@ApiTags('激活码管理')
+@ApiHeader({
+  name: 'Authorization',
+  required: true,
+  description: 'token令牌',
+})
+@ApiBearerAuth()
+@Controller('activation-code')
+@UseInterceptors(LoggerInterceptor)
+@UseGuards(AuthGuard('jwt'))
+export class ActivationCodeController {
+  constructor(private readonly activationCodeService: ActivationCodeService) {}
+
+  /**
+   * @description: 查询激活码列表
+   */
+  @Get()
+  @ApiOkResponse({ type: ResponseActivationCodeDto })
+  @ApiOperation({ summary: '获取激活码列表' })
+  findAll(@Query() params: ActivationCodeParamsDto) {
+    return this.activationCodeService.findAll(params);
+  }
+
+  /**
+   * @description: 创建激活码
+   */
+  @Post()
+  @ApiOkResponse({ type: ResponseSaveActivationCodeDto })
+  @ApiOperation({ summary: '创建激活码' })
+  create(@Body() body: SaveActivationCodeDto) {
+    return this.activationCodeService.create(body);
+  }
+
+  /**
+   * @description: 导出激活码数据
+   */
+  @Get('export')
+  @ApiOperation({ summary: '导出激活码数据' })
+  export(@Query() params: ExportActivationCodeDto) {
+    return this.activationCodeService.export(params);
+  }
+
+  /**
+   * @description: 查询激活码详情
+   */
+  @Get(':id')
+  @ApiOkResponse({ type: ResponseSaveActivationCodeDto })
+  @ApiOperation({ summary: '查询激活码详情' })
+  findOne(@Param('id', new ParseIntPipe()) id: number) {
+    return this.activationCodeService.findOne(id);
+  }
+
+  /**
+   * @description: 更新激活码
+   */
+  @Put(':id')
+  @ApiOkResponse({ type: ResponseSaveActivationCodeDto })
+  @ApiOperation({ summary: '更新激活码' })
+  update(@Param('id', new ParseIntPipe()) id: number, @Body() body: SaveActivationCodeDto) {
+    return this.activationCodeService.update(id, body);
+  }
+
+  /**
+   * @description: 删除激活码
+   */
+  @Delete(':id')
+  @ApiOkResponse({ type: ResponseSaveActivationCodeDto })
+  @ApiOperation({ summary: '删除激活码' })
+  remove(@Param('id', new ParseIntPipe()) id: number) {
+    return this.activationCodeService.remove(id);
+  }
+
+  /**
+   * @description: 激活码激活操作
+   */
+  @Patch(':id/activate')
+  @ApiOkResponse({ type: ResponseSaveActivationCodeDto })
+  @ApiOperation({ summary: '激活码激活' })
+  activate(@Param('id', new ParseIntPipe()) id: number) {
+    return this.activationCodeService.activate(id);
+  }
+
+  /**
+   * @description: 激活码退款操作
+   */
+  @Patch(':id/refund')
+  @ApiOkResponse({ type: ResponseSaveActivationCodeDto })
+  @ApiOperation({ summary: '激活码退款' })
+  refund(@Param('id', new ParseIntPipe()) id: number, @Body() body: RefundActivationCodeDto) {
+    return this.activationCodeService.refund(id, body.refundNote);
+  }
+
+  /**
+   * @description: 激活码收回操作
+   */
+  @Patch(':id/revoke')
+  @ApiOkResponse({ type: ResponseSaveActivationCodeDto })
+  @ApiOperation({ summary: '激活码收回' })
+  revoke(@Param('id', new ParseIntPipe()) id: number) {
+    return this.activationCodeService.revoke(id);
+  }
+
+  /**
+   * @description: 批量导入激活码
+   */
+  @Post('batch-import')
+  @ApiOperation({ summary: '批量导入激活码' })
+  batchImport(@Body() codes: BatchImportActivationCodeArrayDto) {
+    return this.activationCodeService.batchImport(codes);
+  }
+}

+ 15 - 0
server/src/modules/activation-code/activation-code.module.ts

@@ -0,0 +1,15 @@
+import { Module } from '@nestjs/common';
+
+import { PrismaModule } from '@/modules/prisma/prisma.module';
+import { OperationLogModule } from '@/modules/system-manage/operation-log/operation-log.module';
+
+import { ActivationCodeController } from './activation-code.controller';
+import { ActivationCodeService } from './activation-code.service';
+
+@Module({
+  imports: [PrismaModule, OperationLogModule],
+  controllers: [ActivationCodeController],
+  providers: [ActivationCodeService],
+  exports: [ActivationCodeService],
+})
+export class ActivationCodeModule {}

+ 503 - 0
server/src/modules/activation-code/activation-code.service.ts

@@ -0,0 +1,503 @@
+/*
+ * @Description: ActivationCodeService - 激活码管理
+ */
+import { Injectable } from '@nestjs/common';
+import type { ActivationCode, Prisma } from '@prisma/client';
+import * as XLSX from 'xlsx';
+
+import { RESPONSE_MSG } from '@/enums';
+import { PrismaService } from '@/modules/prisma/prisma.service';
+import { responseMessage } from '@/utils';
+
+import { BatchImportActivationCodeArrayDto } from './dto/batch-import-activation-code.dto';
+import { ExportActivationCodeDto } from './dto/export-activation-code.dto';
+import { ActivationCodeParamsDto } from './dto/params-activation-code.dto';
+import { SaveActivationCodeDto } from './dto/save-activation-code.dto';
+
+@Injectable()
+export class ActivationCodeService {
+  constructor(private prisma: PrismaService) {}
+
+
+/**
+ * @description: 构建收回状态查询条件
+ */
+private buildRevokedCondition(revoked?: string | boolean): Prisma.ActivationCodeWhereInput {
+  if (revoked === undefined) return {};
+  
+  // 处理 string 类型
+  if (typeof revoked === 'string') {
+    if (revoked === 'true') {
+      return { revoked: true };
+    } else {
+      return { refunded: true, revoked: false };
+    }
+  }
+  
+  // 处理 boolean 类型
+  if (revoked === true) {
+    return { revoked: true };
+  } else {
+    return { refunded: true, revoked: false };
+  }
+}
+
+/**
+ * @description: 构建日期范围查询条件
+ */
+private buildDateRangeCondition(startDate?: string, endDate?: string): Prisma.ActivationCodeWhereInput {
+  if (!startDate && !endDate) return {};
+  
+  const dateCondition: any = {};
+  if (startDate) {
+    dateCondition.gte = new Date(startDate);
+  }
+  if (endDate) {
+    dateCondition.lte = new Date(endDate);
+  }
+  
+  return { dataDate: dateCondition };
+}
+
+  /**
+   * @description: 查询激活码列表
+   */
+async findAll(params: ActivationCodeParamsDto) {
+  const {
+    code,
+    typeId,
+    activated,
+    refunded,
+    revoked,
+    startDate,
+    endDate,
+    current = 1,
+    size = 10,
+  } = params;
+
+  try {
+    // 构建查询条件
+    const where: Prisma.ActivationCodeWhereInput = {
+      ...(code && { code: { contains: code, mode: 'insensitive' } }),
+      ...(typeId && { typeId }),
+      ...(activated !== undefined && { activated: Boolean(activated) }),
+      ...(refunded !== undefined && { refunded }),
+      ...(this.buildRevokedCondition(revoked)),
+      ...(this.buildDateRangeCondition(startDate, endDate)),
+    };
+
+    // 分页计算
+    const skip = (current - 1) * size;
+    const take = +size;
+
+    // 并行查询
+    const [records, total, infoRecords] = await Promise.all([
+      this.prisma.activationCode.findMany({
+        where,
+        skip,
+        take,
+        orderBy: [
+          { activated: 'asc' },
+          { refunded: 'asc' },
+          { importedAt: 'desc' },
+        ],
+        select: {
+          id: true,
+          code: true,
+          typeId: true,
+          activated: true,
+          refunded: true,
+          revoked: true,
+          activatedAt: true,
+          refundedAt: true,
+          revokedAt: true,
+          dataDate: true,
+          importedAt: true,
+          refundNote: true,
+        },
+      }),
+      this.prisma.activationCode.count({ where }),
+      // 查询 info 数据(只包含需要的字段)
+      this.prisma.activationCode.findMany({
+        where,
+        select: {
+          activated: true,
+          refunded: true,
+          revoked: true,
+          typeId: true,
+        },
+      }),
+    ]);
+
+    return responseMessage<CommonType.PageResponse<ActivationCode>>({
+      records,
+      total,
+      current: +current,
+      size: +size,
+      // 添加 info,只包含需要的字段
+      info: infoRecords,
+    });
+  } catch (error) {
+    return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+  }
+}
+
+  /**
+   * @description: 查询单个激活码
+   */
+  async findOne(id: number) {
+    const result = await this.prisma.activationCode.findUnique({
+      where: { id },
+    });
+
+    if (!result) {
+      return responseMessage(null, '激活码不存在', -1);
+    }
+
+    return responseMessage<ActivationCode>(result);
+  }
+
+  /**
+   * @description: 创建激活码
+   */
+  async create(body: SaveActivationCodeDto) {
+    try {
+      const data = {
+        ...body,
+        activatedAt: body.activatedAt ? new Date(body.activatedAt) : null,
+        refundedAt: body.refundedAt ? new Date(body.refundedAt) : null,
+        revokedAt: body.revokedAt ? new Date(body.revokedAt) : null,
+        dataDate: new Date(body.dataDate),
+      };
+
+      const result = await this.prisma.activationCode.create({
+        data,
+      });
+
+      return responseMessage<ActivationCode>(result);
+    } catch (error) {
+      // 判断是否违反唯一性约束
+      if (error.code === 'P2002') {
+        return responseMessage(null, '激活码已存在!', -1);
+      }
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 更新激活码
+   */
+  async update(id: number, body: SaveActivationCodeDto) {
+    try {
+      // 检查激活码是否存在
+      const existingCode = await this.prisma.activationCode.findUnique({
+        where: { id },
+      });
+
+      if (!existingCode) {
+        return responseMessage(null, '激活码不存在', -1);
+      }
+
+      const data = {
+        ...body,
+        activatedAt: body.activatedAt ? new Date(body.activatedAt) : null,
+        refundedAt: body.refundedAt ? new Date(body.refundedAt) : null,
+        revokedAt: body.revokedAt ? new Date(body.revokedAt) : null,
+        dataDate: new Date(body.dataDate),
+      };
+
+      const result = await this.prisma.activationCode.update({
+        where: { id },
+        data,
+      });
+
+      return responseMessage<ActivationCode>(result);
+    } catch (error) {
+      // 判断是否违反唯一性约束
+      if (error.code === 'P2002') {
+        return responseMessage(null, '激活码已存在!', -1);
+      }
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 删除激活码
+   */
+  async remove(id: number) {
+    try {
+      // 检查激活码是否存在
+      const existingCode = await this.prisma.activationCode.findUnique({
+        where: { id },
+      });
+
+      if (!existingCode) {
+        return responseMessage(null, '激活码不存在', -1);
+      }
+
+      const result = await this.prisma.activationCode.delete({
+        where: { id },
+      });
+
+      return responseMessage<ActivationCode>(result, '删除成功');
+    } catch (error) {
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 激活码激活/取消激活操作
+   */
+  async activate(id: number) {
+    try {
+      const existingCode = await this.prisma.activationCode.findUnique({
+        where: { id },
+      });
+
+      if (!existingCode) {
+        return responseMessage(null, '激活码不存在', -1);
+      }
+
+      // 如果已激活,则取消激活
+      if (existingCode.activated) {
+        const result = await this.prisma.activationCode.update({
+          where: { id },
+          data: {
+            activated: false,
+            activatedAt: null,
+            // 如果取消激活,同时取消退款和收回状态
+            refunded: false,
+            refundedAt: null,
+            refundNote: null,
+            revoked: false,
+            revokedAt: null,
+          },
+        });
+        return responseMessage<ActivationCode>(result, '已取消激活');
+      }
+
+      // 如果未激活,则激活
+      const result = await this.prisma.activationCode.update({
+        where: { id },
+        data: {
+          activated: true,
+          activatedAt: new Date(),
+        },
+      });
+
+      return responseMessage<ActivationCode>(result, '激活成功');
+    } catch (error) {
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 激活码退款/取消退款操作
+   */
+  async refund(id: number, refundNote?: string) {
+    try {
+      const existingCode = await this.prisma.activationCode.findUnique({
+        where: { id },
+      });
+
+      if (!existingCode) {
+        return responseMessage(null, '激活码不存在', -1);
+      }
+
+      if (!existingCode.activated) {
+        return responseMessage(null, '激活码未激活,无法操作', -1);
+      }
+
+      // 如果已退款,则取消退款
+      if (existingCode.refunded) {
+        const result = await this.prisma.activationCode.update({
+          where: { id },
+          data: {
+            refunded: false,
+            refundedAt: null,
+            refundNote: null,
+          },
+        });
+        return responseMessage<ActivationCode>(result, '已取消退款');
+      }
+
+      // 如果未退款,则退款
+      const result = await this.prisma.activationCode.update({
+        where: { id },
+        data: {
+          refunded: true,
+          refundedAt: new Date(),
+          refundNote: refundNote || '退款',
+        },
+      });
+
+      return responseMessage<ActivationCode>(result, '退款成功');
+    } catch (error) {
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 激活码收回/取消收回操作
+   */
+  async revoke(id: number) {
+    try {
+      const existingCode = await this.prisma.activationCode.findUnique({
+        where: { id },
+      });
+
+      if (!existingCode) {
+        return responseMessage(null, '激活码不存在', -1);
+      }
+
+      if (!existingCode.activated) {
+        return responseMessage(null, '激活码未激活,无法操作', -1);
+      }
+
+      // 如果已收回,则取消收回
+      if (existingCode.revoked) {
+        const result = await this.prisma.activationCode.update({
+          where: { id },
+          data: {
+            revoked: false,
+            revokedAt: null,
+          },
+        });
+        return responseMessage<ActivationCode>(result, '已取消收回');
+      }
+
+      // 如果未收回,则收回
+      const result = await this.prisma.activationCode.update({
+        where: { id },
+        data: {
+          revoked: true,
+          revokedAt: new Date(),
+        },
+      });
+
+      return responseMessage<ActivationCode>(result, '收回成功');
+    } catch (error) {
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 批量导入激活码
+   */
+  async batchImport(codes: BatchImportActivationCodeArrayDto) {
+    try {
+      const data = codes.map((item) => {
+        // 验证至少有一个类型字段
+        if (!item.type && !item.typeId) {
+          throw new Error(`激活码 ${item.code} 必须提供 type 或 typeId`);
+        }
+
+        const baseData = {
+          code: item.code,
+          type: item.type || 0, // 确保 type 字段始终有值(Prisma 要求)
+          dataDate: new Date(item.dataDate),
+          importedAt: new Date(),
+        };
+
+        // 如果提供了新的 typeId,则添加关联
+        if (item.typeId) {
+          return { ...baseData, typeId: item.typeId };
+        }
+
+        return baseData;
+      });
+
+      const result = await this.prisma.activationCode.createMany({
+        data,
+        skipDuplicates: true, // 跳过重复的激活码
+      });
+
+      return responseMessage({ count: result.count }, `成功导入 ${result.count} 个激活码`);
+    } catch (error) {
+      if (error.message) {
+        return responseMessage(null, error.message, -1);
+      }
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 导出激活码数据
+   */
+  async export(params: ExportActivationCodeDto) {
+    try {
+      const { startDate, endDate } = params;
+
+      // 构建查询条件
+      const where: any = {};
+
+      // 日期范围查询
+      if (startDate || endDate) {
+        where.dataDate = {};
+        if (startDate) {
+          where.dataDate.gte = new Date(startDate);
+        }
+        if (endDate) {
+          where.dataDate.lte = new Date(endDate);
+        }
+      }
+
+      // 查询所有符合条件的数据
+      const records = await this.prisma.activationCode.findMany({
+        where,
+        orderBy: [{ dataDate: 'desc' }, { importedAt: 'desc' }],
+        include: { codeType: true },
+      });
+
+      // 转换数据格式用于导出
+      const exportData = records.map((record) => ({
+        激活码: record.code,
+        类型: record.codeType?.name || `${record.type}天KEY`,
+        导入时间: record.importedAt.toISOString().split('T')[0],
+        已激活: record.activated ? '是' : '否',
+        激活时间: record.activatedAt ? record.activatedAt.toISOString().split('T')[0] : '',
+        已退款: record.refunded ? '是' : '否',
+        退款时间: record.refundedAt ? record.refundedAt.toISOString().split('T')[0] : '',
+        退款原因: record.refundNote || '',
+        已收回: record.revoked ? '是' : '否',
+        收回时间: record.revokedAt ? record.revokedAt.toISOString().split('T')[0] : '',
+        // 数据日期: record.dataDate.toISOString().split('T')[0],
+      }));
+
+      // Excel格式导出
+      const worksheet = XLSX.utils.json_to_sheet(exportData);
+      const workbook = XLSX.utils.book_new();
+      XLSX.utils.book_append_sheet(workbook, worksheet, '激活码数据');
+
+      // 设置列宽
+      const colWidths = [
+        { wch: 20 }, // 激活码
+        { wch: 12 }, // 类型
+        { wch: 12 }, // 导入时间
+        { wch: 8 }, // 已激活
+        { wch: 12 }, // 激活时间
+        { wch: 8 }, // 已退款
+        { wch: 12 }, // 退款时间
+        { wch: 20 }, // 退款原因
+        { wch: 8 }, // 已收回
+        { wch: 12 }, // 收回时间
+        { wch: 12 }, // 数据日期
+      ];
+      worksheet['!cols'] = colWidths;
+
+      // 生成Buffer
+      const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'buffer' });
+
+      return responseMessage(
+        {
+          data: excelBuffer.toString('base64'), // 返回base64编码的数据
+          count: exportData.length,
+          filename: `激活码数据_${new Date().toISOString().split('T')[0]}.xlsx`,
+        },
+        '导出成功',
+      );
+    } catch (error) {
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+}

+ 42 - 0
server/src/modules/activation-code/dto/batch-import-activation-code.dto.ts

@@ -0,0 +1,42 @@
+/*
+ * @Description: 批量导入激活码数据 Dto
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { IsDateString, IsNotEmpty, IsOptional, IsString } from 'class-validator';
+
+export class BatchImportActivationCodeDto {
+  @ApiProperty({
+    type: String,
+    description: '激活码唯一字符串',
+  })
+  @IsNotEmpty({ message: '激活码必填' })
+  @IsString({ message: '激活码必须是字符串' })
+  code: string;
+
+  @ApiProperty({
+    type: Number,
+    description: '类型(激活天数,旧字段,向后兼容)',
+    required: false,
+  })
+  @IsOptional()
+  type?: number;
+
+  @ApiProperty({
+    type: String,
+    description: '激活码类型ID(新字段)',
+    required: false,
+  })
+  @IsOptional()
+  @IsString({ message: '类型ID必须是字符串' })
+  typeId?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '数据日期',
+  })
+  @IsNotEmpty({ message: '数据日期必填' })
+  @IsDateString({}, { message: '数据日期格式不正确' })
+  dataDate: string;
+}
+
+export type BatchImportActivationCodeArrayDto = BatchImportActivationCodeDto[];

+ 35 - 0
server/src/modules/activation-code/dto/export-activation-code.dto.ts

@@ -0,0 +1,35 @@
+/*
+ * @Description: 激活码导出参数 DTO
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { IsDateString, IsOptional } from 'class-validator';
+
+export class ExportActivationCodeDto {
+  @ApiProperty({
+    type: String,
+    description: '开始日期',
+    required: false,
+  })
+  @IsOptional()
+  @IsDateString({}, { message: '开始日期格式不正确' })
+  startDate?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '结束日期',
+    required: false,
+  })
+  @IsOptional()
+  @IsDateString({}, { message: '结束日期格式不正确' })
+  endDate?: string;
+
+  // @ApiProperty({
+  //   enum: ACTIVATION_CODE_TYPE,
+  //   description: '类型(激活天数)',
+  //   required: false,
+  // })
+  // @IsOptional()
+  // @Transform(({ value }) => (value ? parseInt(value, 10) : undefined))
+  // @IsEnum(ACTIVATION_CODE_TYPE, { message: '类型必须是有效的激活码类型' })
+  // type?: ACTIVATION_CODE_TYPE;
+}

+ 98 - 0
server/src/modules/activation-code/dto/params-activation-code.dto.ts

@@ -0,0 +1,98 @@
+/*
+ * @Description: 激活码查询参数 DTO
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { Transform } from 'class-transformer';
+import { IsBoolean, IsDateString, IsInt, IsOptional, IsString, IsUUID, Min } from 'class-validator';
+
+export class ActivationCodeParamsDto {
+  @ApiProperty({
+    type: String,
+    description: '激活码(模糊搜索)',
+    required: false,
+  })
+  @IsOptional()
+  @IsString()
+  code?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '类型(激活天数)',
+    required: false,
+  })
+  @IsOptional()
+  @IsUUID('all', { message: '类型必须是有效的激活码类型' })
+  typeId?: string;
+
+  @ApiProperty({
+    type: Boolean,
+    description: '是否已激活',
+    required: false,
+  })
+  @IsOptional()
+  @Transform(({ value }) => value === 'true' || value === true)
+  @IsBoolean()
+  activated?: boolean;
+
+  @ApiProperty({
+    type: Boolean,
+    description: '是否已退款',
+    required: false,
+  })
+  @IsOptional()
+  @Transform(({ value }) => value === 'true' || value === true)
+  @IsBoolean()
+  refunded?: boolean;
+
+  @ApiProperty({
+    type: Boolean,
+    description: '是否已收回',
+    required: false,
+  })
+  @IsOptional()
+  @Transform(({ value }) => value === 'true' || value === true)
+  @IsBoolean()
+  revoked?: boolean | string;
+
+  @ApiProperty({
+    type: String,
+    description: '数据日期开始时间',
+    required: false,
+  })
+  @IsOptional()
+  @IsDateString({}, { message: '开始时间格式不正确' })
+  startDate?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '数据日期结束时间',
+    required: false,
+  })
+  @IsOptional()
+  @IsDateString({}, { message: '结束时间格式不正确' })
+  endDate?: string;
+
+  @ApiProperty({
+    type: Number,
+    description: '当前页码',
+    default: 1,
+    required: false,
+  })
+  @IsOptional()
+  @Transform(({ value }) => parseInt(value, 10))
+  @IsInt({ message: 'current 参数只能是 number 类型' })
+  @Min(1, { message: 'current 参数不能小于 1' })
+  current?: number = 1;
+
+  @ApiProperty({
+    type: Number,
+    description: '每页条数',
+    default: 10,
+    required: false,
+  })
+  @IsOptional()
+  @Transform(({ value }) => parseInt(value, 10))
+  @IsInt({ message: 'size 参数只能是 number 类型' })
+  @Min(1, { message: 'size 参数不能小于 1' })
+  size?: number = 10;
+}

+ 17 - 0
server/src/modules/activation-code/dto/refund-activation-code.dto.ts

@@ -0,0 +1,17 @@
+/*
+ * @Description: 激活码退款操作 DTO
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { IsOptional, IsString } from 'class-validator';
+
+export class RefundActivationCodeDto {
+  @ApiProperty({
+    type: String,
+    description: '退款备注(例如原因)',
+    required: false,
+    default: '用户申请退款',
+  })
+  @IsOptional()
+  @IsString({ message: '退款备注必须是字符串' })
+  refundNote?: string;
+}

+ 66 - 0
server/src/modules/activation-code/dto/response-activation-code.dto.ts

@@ -0,0 +1,66 @@
+/*
+ * @Description: 激活码响应体 DTO
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import type { ActivationCode } from '@prisma/client';
+
+import { ResponseDto } from '@/dto/response.dto';
+
+import { ACTIVATION_CODE_TYPE } from '../enums';
+
+/**
+ * @description: 激活码列表响应体结构 Dto
+ */
+export class ResponseActivationCodeDto extends ResponseDto {
+  @ApiProperty({
+    type: Object,
+    description: '响应体',
+    default: {
+      records: [
+        {
+          id: 1,
+          code: 'ACT-2024-0001-XXXX',
+          type: ACTIVATION_CODE_TYPE.DAY_30,
+          importedAt: '2024-01-01T00:00:00.000Z',
+          activated: false,
+          activatedAt: null,
+          refunded: false,
+          refundedAt: null,
+          refundNote: null,
+          revoked: false,
+          revokedAt: null,
+          dataDate: '2024-01-01T00:00:00.000Z',
+        },
+      ],
+      current: 1,
+      size: 10,
+      total: 1,
+    },
+  })
+  data: CommonType.PageResponse<ActivationCode>;
+}
+
+/**
+ * @description: 创建/更新/删除激活码数据 Dto
+ */
+export class ResponseSaveActivationCodeDto extends ResponseDto {
+  @ApiProperty({
+    type: Object,
+    description: '响应体',
+    default: {
+      id: 1,
+      code: 'ACT-2024-0001-XXXX',
+      type: ACTIVATION_CODE_TYPE.DAY_30,
+      importedAt: '2024-01-01T00:00:00.000Z',
+      activated: false,
+      activatedAt: null,
+      refunded: false,
+      refundedAt: null,
+      refundNote: null,
+      revoked: false,
+      revokedAt: null,
+      dataDate: '2024-01-01T00:00:00.000Z',
+    },
+  })
+  data: ActivationCode;
+}

+ 102 - 0
server/src/modules/activation-code/dto/save-activation-code.dto.ts

@@ -0,0 +1,102 @@
+/*
+ * @Description: 保存激活码数据 Dto
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { IsBoolean, IsDateString, IsEnum, IsNotEmpty, IsOptional, IsString } from 'class-validator';
+
+import { ACTIVATION_CODE_TYPE } from '../enums';
+
+export class SaveActivationCodeDto {
+  @ApiProperty({
+    type: String,
+    description: '激活码唯一字符串',
+    default: 'ACT-2024-XXXX-XXXX',
+  })
+  @IsNotEmpty({ message: '激活码必填' })
+  @IsString({ message: '激活码必须是字符串' })
+  code: string;
+
+  @ApiProperty({
+    enum: ACTIVATION_CODE_TYPE,
+    description: '类型(激活天数)',
+    default: ACTIVATION_CODE_TYPE.DAY_30,
+  })
+  @IsNotEmpty({ message: '类型必填' })
+  @IsEnum(ACTIVATION_CODE_TYPE, { message: '类型必须是有效的激活码类型' })
+  type: ACTIVATION_CODE_TYPE;
+
+  @ApiProperty({
+    type: Boolean,
+    description: '是否已激活',
+    default: false,
+    required: false,
+  })
+  @IsOptional()
+  @IsBoolean({ message: '激活状态必须是布尔值' })
+  activated?: boolean;
+
+  @ApiProperty({
+    type: String,
+    description: '激活时间',
+    required: false,
+  })
+  @IsOptional()
+  @IsDateString({}, { message: '激活时间格式不正确' })
+  activatedAt?: string;
+
+  @ApiProperty({
+    type: Boolean,
+    description: '是否已退款',
+    default: false,
+    required: false,
+  })
+  @IsOptional()
+  @IsBoolean({ message: '退款状态必须是布尔值' })
+  refunded?: boolean;
+
+  @ApiProperty({
+    type: String,
+    description: '退款时间',
+    required: false,
+  })
+  @IsOptional()
+  @IsDateString({}, { message: '退款时间格式不正确' })
+  refundedAt?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '退款备注(例如原因)',
+    required: false,
+  })
+  @IsOptional()
+  @IsString({ message: '退款备注必须是字符串' })
+  refundNote?: string;
+
+  @ApiProperty({
+    type: Boolean,
+    description: '是否已收回',
+    default: false,
+    required: false,
+  })
+  @IsOptional()
+  @IsBoolean({ message: '收回状态必须是布尔值' })
+  revoked?: boolean;
+
+  @ApiProperty({
+    type: String,
+    description: '收回时间',
+    required: false,
+  })
+  @IsOptional()
+  @IsDateString({}, { message: '收回时间格式不正确' })
+  revokedAt?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '数据日期,用于数据归属时间',
+  })
+  // @IsNotEmpty({ message: '数据日期必填' })
+  @IsOptional()
+  @IsDateString({}, { message: '数据日期格式不正确' })
+  dataDate?: string;
+}

+ 8 - 0
server/src/modules/activation-code/enums/index.ts

@@ -0,0 +1,8 @@
+// 激活码类型 1天KEY 15天KEY 30天KEY 182天KEY 365天KEY
+export enum ACTIVATION_CODE_TYPE {
+  DAY_1 = 1,
+  DAY_15 = 15,
+  DAY_30 = 30,
+  DAY_182 = 182,
+  DAY_365 = 365,
+}

+ 61 - 0
server/src/modules/administrative/message/dto/params-message.dto.ts

@@ -0,0 +1,61 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-09-02 14:15:22
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-09-02 14:19:05
+ * @Description: 请求参数 DTO
+ */
+
+import { ApiProperty } from '@nestjs/swagger';
+import { Status } from '@prisma/client';
+import { IsNumberString, IsOptional, IsUUID } from 'class-validator';
+
+import { PaginatingDTO } from '@/dto/params.dto';
+
+export class MessageParamsDto extends PaginatingDTO {
+  @ApiProperty({
+    type: String,
+    description: '作者 id',
+    default: 'f45cd48b-e703-49db-91be-ae7f594e73e0',
+    required: false,
+  })
+  @IsOptional()
+  @IsUUID('all', { message: 'userId 参数不正确' })
+  userId?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '标题',
+    default: '全红婵夺冠拉',
+    required: false,
+  })
+  title?: string;
+
+  @ApiProperty({
+    enum: Status,
+    description: '状态',
+    default: Status.ACTIVE,
+    required: false,
+  })
+  status?: Status;
+
+  @ApiProperty({
+    type: Number,
+    description: '开始日期',
+    default: 1721145600000,
+    required: false,
+  })
+  @IsOptional()
+  @IsNumberString({}, { message: '开始日期必须是时间戳格式' })
+  startTime?: number;
+
+  @ApiProperty({
+    type: Number,
+    description: '结束日期',
+    default: 1721318399999,
+    required: false,
+  })
+  @IsOptional()
+  @IsNumberString({}, { message: '结束日期必须是时间戳格式' })
+  endTime?: number;
+}

+ 193 - 0
server/src/modules/administrative/message/dto/response-message.dto.ts

@@ -0,0 +1,193 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-09-02 14:26:40
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-09-04 10:56:03
+ * @Description: 响应体
+ */
+
+import { ApiProperty } from '@nestjs/swagger';
+import type { Message, MessageRead } from '@prisma/client';
+
+import { ResponseDto } from '@/dto/response.dto';
+
+/**
+ * @description: 消息公告列表响应体结构 Dto
+ */
+export class ResponseMessageDto extends ResponseDto {
+  @ApiProperty({
+    type: Array,
+    description: '响应体',
+    default: {
+      records: [
+        {
+          id: 'b64c3c94-5312-45f2-aa8f-fca11a04263a',
+          title: '泰安交通事故致十余名学生死伤',
+          content:
+            '<p>【<a href="https://s.weibo.com/weibo?q=%23%E6%B3%B0%E5%AE%89%E4%BA%A4%E9%80%9A%E4%BA%8B%E6%95%85%E8%87%B4%E5%8D%81%E4%BD%99%E5%90%8D%E5%AD%A6%E7%94%9F%E6%AD%BB%E4%BC%A4%23" target="_blank">#泰安交通事故致十余名学生死伤#</a>】记者9月3日从山东省泰安市东平县相关部门获悉,上午7点多当地一所中学门口发生一起严重交通事故,一辆接送学生的定制公交车冲进路边正在上学的学生人群中,目前已造成十几名学生死伤。(新华社) ​​​</p><p><br></p><ul><li style="text-align: center;"><img src="https://wx3.sinaimg.cn/orj360/001PVG9Vly1htac0c4fg3j60z20vvgqx02.jpg" alt="" data-href="" style="width: auto;height: 167px;"><br></li></ul>',
+          status: 'ACTIVE',
+          pinned: false,
+          userId: 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f',
+          createdAt: '2024-09-03T03:32:14.656Z',
+          updatedAt: '2024-09-03T03:32:14.656Z',
+          user: {
+            id: 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f',
+            userName: 'Admin',
+            password: '$2b$10$lfMvyYSrWNjVF55UhxeC0uoVYgf7GwWBhXu1BZAlvHXoGf./E7Lk2',
+            cnName: '谢明伟',
+            email: 'baiwumm@foxmail.com',
+            phone: '15920157932',
+            avatar: 'http://localhost:3000/static/image/2024-07/cc9e77ee-cf84-48e8-a9d0-dc3e9d21224c.jpeg',
+            sex: 'MALE',
+            status: 'ACTIVE',
+            sort: 88,
+            token: null,
+            tags: ['热血青年', '佛系', '追求自由', '做自己喜欢做的事'],
+            city: ['44', '4403', '440305'],
+            address: '粤海街道',
+            roleId: '6db049fe-c944-4680-b6dc-f9f40d6ad018',
+            orgId: '32cab8f0-13df-4876-83c5-86089390dbb7',
+            postId: '34f2d5e1-7378-46b3-8f0c-56cfdbb8f3eb',
+            loginCount: 163,
+            lastIp: '::1',
+            lastLoginAt: '2024-09-03T02:45:50.342Z',
+            createdAt: '2024-07-30T02:35:25.835Z',
+            updatedAt: '2024-09-03T03:33:28.195Z',
+          },
+          messageReads: [],
+        },
+      ],
+      total: 100,
+      current: 1,
+      size: 10,
+    },
+  })
+  data: Message[];
+}
+
+/**
+ * @description: 创建/更新/消息数据 Dto
+ */
+export class ResponseSaveMessageDto extends ResponseDto {
+  @ApiProperty({
+    type: Object,
+    description: '响应体',
+    default: {
+      id: 'b64c3c94-5312-45f2-aa8f-fca11a04263a',
+      title: '泰安交通事故致十余名学生死伤',
+      content:
+        '<p>【<a href="https://s.weibo.com/weibo?q=%23%E6%B3%B0%E5%AE%89%E4%BA%A4%E9%80%9A%E4%BA%8B%E6%95%85%E8%87%B4%E5%8D%81%E4%BD%99%E5%90%8D%E5%AD%A6%E7%94%9F%E6%AD%BB%E4%BC%A4%23" target="_blank">#泰安交通事故致十余名学生死伤#</a>】记者9月3日从山东省泰安市东平县相关部门获悉,上午7点多当地一所中学门口发生一起严重交通事故,一辆接送学生的定制公交车冲进路边正在上学的学生人群中,目前已造成十几名学生死伤。(新华社) ​​​</p><p><br></p><ul><li style="text-align: center;"><img src="https://wx3.sinaimg.cn/orj360/001PVG9Vly1htac0c4fg3j60z20vvgqx02.jpg" alt="" data-href="" style="width: auto;height: 167px;"><br></li></ul>',
+      status: 'ACTIVE',
+      pinned: false,
+      userId: 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f',
+      createdAt: '2024-09-03T03:32:14.656Z',
+      updatedAt: '2024-09-03T03:32:14.656Z',
+    },
+  })
+  data: Message;
+}
+
+/**
+ * @description: 删除消息数据 Dto
+ */
+export class ResponseDeleteMessageDto extends ResponseDto {
+  @ApiProperty({
+    type: [Object, Object],
+    description: '响应体',
+    default: [
+      {
+        count: 1,
+      },
+      {
+        id: '42e27ded-ba63-45ea-962b-e49580a32095',
+        title: '青岛警方通报王某驾车逆行殴打他人案',
+        content:
+          '<p>【<a href="https://s.weibo.com/weibo?q=%23%E9%9D%92%E5%B2%9B%E8%AD%A6%E6%96%B9%E9%80%9A%E6%8A%A5%E7%8E%8B%E6%9F%90%E9%A9%BE%E8%BD%A6%E9%80%86%E8%A1%8C%E6%AE%B4%E6%89%93%E4%BB%96%E4%BA%BA%E6%A1%88%23" target="_blank">#青岛警方通报王某驾车逆行殴打他人案#</a>】<a href="https://s.weibo.com/weibo?q=%23%E7%BD%91%E4%BC%A0%E9%80%86%E8%A1%8C%E6%89%93%E4%BA%BA%E5%8F%B8%E6%9C%BA%E8%A2%AB%E5%B1%85%E5%AE%B6%E6%8B%98%E7%95%99%E4%B8%8D%E5%B1%9E%E5%AE%9E%23" target="_blank">#网传逆行打人司机被居家拘留不属实#</a> 近日,青岛市崂山区“王某驾车逆行辱骂殴打他人”案件引发关注,青岛市公安局成立工作专班,依法进行了核查,现将有关情况通报如下↓↓(人民日报记者侯琳良、王沛) ​</p><p><br></p><ul><li style="text-align: center;"><img src="https://wx1.sinaimg.cn/orj360/0033ImPzly1htag9nhazqj60ku408b2b02.jpg" alt="" data-href="" style="width: 167px;height: auto;"><br></li></ul>',
+        status: 'ACTIVE',
+        pinned: false,
+        userId: 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f',
+        createdAt: '2024-09-03T10:00:02.340Z',
+        updatedAt: '2024-09-03T10:00:02.340Z',
+      },
+    ],
+  })
+  data: [{ count: number }, Message];
+}
+
+/**
+ * @description: 创建已读信息 Dto
+ */
+export class ResponseSaveMessageReadDto extends ResponseDto {
+  @ApiProperty({
+    type: Object,
+    description: '响应体',
+    default: {
+      id: '8d1b1833-08bd-44a0-8837-17d1ae64d917',
+      messageId: '42e27ded-ba63-45ea-962b-e49580a32095',
+      userId: 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f',
+      createdAt: '2024-09-04T02:09:08.542Z',
+    },
+  })
+  data: MessageRead;
+}
+
+/**
+ * @description: 未读消息条数 Dto
+ */
+export class UnReadMessageCountDto extends ResponseDto {
+  @ApiProperty({
+    type: Object,
+    description: '响应体',
+    default: 10,
+  })
+  data: number;
+}
+
+/**
+ * @description: 未读消息列表 Dto
+ */
+export class UnReadMessageDto extends ResponseDto {
+  @ApiProperty({
+    type: Array,
+    description: '响应体',
+    default: [
+      {
+        id: 'b64c3c94-5312-45f2-aa8f-fca11a04263a',
+        title: '泰安交通事故致十余名学生死伤',
+        content:
+          '<p>【<a href="https://s.weibo.com/weibo?q=%23%E6%B3%B0%E5%AE%89%E4%BA%A4%E9%80%9A%E4%BA%8B%E6%95%85%E8%87%B4%E5%8D%81%E4%BD%99%E5%90%8D%E5%AD%A6%E7%94%9F%E6%AD%BB%E4%BC%A4%23" target="_blank">#泰安交通事故致十余名学生死伤#</a>】记者9月3日从山东省泰安市东平县相关部门获悉,上午7点多当地一所中学门口发生一起严重交通事故,一辆接送学生的定制公交车冲进路边正在上学的学生人群中,目前已造成十几名学生死伤。(新华社) ​​​</p><p><br></p><ul><li style="text-align: center;"><img src="https://wx3.sinaimg.cn/orj360/001PVG9Vly1htac0c4fg3j60z20vvgqx02.jpg" alt="" data-href="" style="width: auto;height: 167px;"><br></li></ul>',
+        status: 'ACTIVE',
+        pinned: false,
+        userId: 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f',
+        createdAt: '2024-09-03T03:32:14.656Z',
+        updatedAt: '2024-09-03T03:32:14.656Z',
+        user: {
+          id: 'dddd7ba9-c1d4-4a6b-b946-f05e2f79880f',
+          userName: 'Admin',
+          password: '$2b$10$lfMvyYSrWNjVF55UhxeC0uoVYgf7GwWBhXu1BZAlvHXoGf./E7Lk2',
+          cnName: '谢明伟',
+          email: 'baiwumm@foxmail.com',
+          phone: '15920157932',
+          avatar: 'http://localhost:3000/static/image/2024-07/cc9e77ee-cf84-48e8-a9d0-dc3e9d21224c.jpeg',
+          sex: 'MALE',
+          status: 'ACTIVE',
+          sort: 88,
+          token: null,
+          tags: ['热血青年', '佛系', '追求自由', '做自己喜欢做的事'],
+          city: ['44', '4403', '440305'],
+          address: '粤海街道',
+          roleId: '6db049fe-c944-4680-b6dc-f9f40d6ad018',
+          orgId: '32cab8f0-13df-4876-83c5-86089390dbb7',
+          postId: '34f2d5e1-7378-46b3-8f0c-56cfdbb8f3eb',
+          loginCount: 163,
+          lastIp: '::1',
+          lastLoginAt: '2024-09-03T02:45:50.342Z',
+          createdAt: '2024-07-30T02:35:25.835Z',
+          updatedAt: '2024-09-03T03:33:28.195Z',
+        },
+        messageReads: [],
+      },
+    ],
+  })
+  data: Message[];
+}

+ 55 - 0
server/src/modules/administrative/message/dto/save-message.dto.ts

@@ -0,0 +1,55 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-09-02 15:58:30
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-09-02 16:03:30
+ * @Description: 保存消息公告
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { Status } from '@prisma/client';
+import { IsNotEmpty } from 'class-validator';
+
+export class SaveMessageDto {
+  @ApiProperty({
+    type: String,
+    description: '标题',
+    default: '中秋节放假通知',
+  })
+  @IsNotEmpty({ message: '标题必填' })
+  title: string;
+
+  @ApiProperty({
+    type: String,
+    description: '内容',
+    default: '中秋节放假通知',
+  })
+  @IsNotEmpty({ message: '内容必填' })
+  content: string;
+
+  @ApiProperty({
+    enum: Status,
+    description: '状态',
+    example: Status.ACTIVE,
+  })
+  status: Status;
+
+  @ApiProperty({
+    type: Boolean,
+    description: '是否置顶',
+    default: false,
+  })
+  pinned: boolean;
+}
+
+/**
+ * @description: 创建已读信息
+ */
+export class SaveMessageReadDto {
+  @ApiProperty({
+    type: String,
+    description: '消息 id',
+    default: 'b64c3c94-5312-45f2-aa8f-fca11a04263a',
+  })
+  @IsNotEmpty({ message: '消息 id 必填' })
+  id: string;
+}

+ 165 - 0
server/src/modules/administrative/message/message.controller.ts

@@ -0,0 +1,165 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-09-02 14:24:39
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-09-09 10:08:37
+ * @Description: MessageController
+ */
+import {
+  Body,
+  Controller,
+  Delete,
+  Get,
+  Param,
+  ParseUUIDPipe,
+  Patch,
+  Post,
+  Put,
+  Query,
+  Session,
+  Sse,
+  UseGuards,
+  UseInterceptors,
+} from '@nestjs/common';
+import { EventEmitter2 } from '@nestjs/event-emitter';
+import { AuthGuard } from '@nestjs/passport';
+import { ApiBearerAuth, ApiHeader, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; // swagger 接口文档
+import type { Message } from '@prisma/client';
+import { Observable } from 'rxjs';
+
+import { PaginatingDTO } from '@/dto/params.dto';
+import { EVENTBUS_TYPE } from '@/enums';
+import { LoggerInterceptor } from '@/interceptor/logger.interceptor';
+
+import { MessageParamsDto } from './dto/params-message.dto';
+import {
+  ResponseMessageDto,
+  ResponseSaveMessageReadDto,
+  UnReadMessageCountDto,
+  UnReadMessageDto,
+} from './dto/response-message.dto';
+import { SaveMessageDto, SaveMessageReadDto } from './dto/save-message.dto';
+import { MessageService } from './message.service';
+
+@ApiTags('智能行政-消息公告')
+@ApiHeader({
+  name: 'Authorization',
+  required: true,
+  description: 'token令牌',
+})
+@ApiBearerAuth()
+@Controller('administrative/message')
+@UseInterceptors(LoggerInterceptor)
+@UseGuards(AuthGuard('jwt'))
+export class MessageController {
+  constructor(
+    private readonly messageService: MessageService,
+    private eventEmitter: EventEmitter2,
+  ) { }
+
+  /**
+   * @description: 查询消息公告列表
+   */
+  @Get()
+  @ApiOkResponse({ type: ResponseMessageDto })
+  @ApiOperation({ summary: '获取消息公告列表' })
+  findAll(@Query() params: MessageParamsDto) {
+    return this.messageService.findAll(params);
+  }
+
+  /**
+   * @description: 查询消息公告详情
+   */
+  @Get(':id')
+  @ApiOkResponse({ type: ResponseMessageDto })
+  @ApiOperation({ summary: '查询消息公告详情' })
+  findOne(@Param('id', new ParseUUIDPipe()) id: string) {
+    return this.messageService.findOne(id);
+  }
+
+  /**
+   * @description: 创建消息公告
+   */
+  @Post()
+  @ApiOkResponse({ type: ResponseMessageDto })
+  @ApiOperation({ summary: '创建消息公告' })
+  async create(@Body() body: SaveMessageDto, @Session() session: CommonType.SessionInfo) {
+    const result = await this.messageService.create(body, session);
+    // 消息创建成功后,发送一个消息
+    this.eventEmitter.emit(EVENTBUS_TYPE.MESSAGE_CREATE, result.data);
+    return result;
+  }
+
+  /**
+   * @description: 服务端推送事件
+   */
+  @Sse('sse/event')
+  sse(): Observable<MessageEvent> {
+    return new Observable<any>((observer) => {
+      // 监听事件
+      this.eventEmitter.on(EVENTBUS_TYPE.MESSAGE_CREATE, (data: Message) => {
+        observer.next({ data });
+      });
+    });
+  }
+
+  /**
+   * @description: 更新消息公告
+   */
+  @Put(':id')
+  @ApiOkResponse({ type: ResponseMessageDto })
+  @ApiOperation({ summary: '更新消息公告' })
+  update(@Param('id', new ParseUUIDPipe()) id: string, @Body() body: SaveMessageDto) {
+    return this.messageService.update(id, body);
+  }
+
+  /**
+   * @description: 删除消息公告
+   */
+  @Delete(':id')
+  @ApiOkResponse({ type: ResponseMessageDto })
+  @ApiOperation({ summary: '删除消息公告' })
+  remove(@Param('id', new ParseUUIDPipe()) id: string) {
+    return this.messageService.remove(id);
+  }
+
+  /**
+   * @description: 修改置顶状态
+   */
+  @Patch(':id')
+  @ApiOkResponse({ type: ResponseMessageDto })
+  @ApiOperation({ summary: '修改置顶状态' })
+  changePinned(@Param('id', new ParseUUIDPipe()) id: string) {
+    return this.messageService.changePinned(id);
+  }
+
+  /**
+   * @description: 创建已读信息
+   */
+  @Post('/createMessageRead')
+  @ApiOkResponse({ type: ResponseSaveMessageReadDto })
+  @ApiOperation({ summary: '创建已读信息' })
+  createMessageRead(@Body() body: SaveMessageReadDto, @Session() session: CommonType.SessionInfo) {
+    return this.messageService.createMessageRead(body.id, session);
+  }
+
+  /**
+   * @description: 查询未读消息条数
+   */
+  @Get('/unread/count')
+  @ApiOkResponse({ type: UnReadMessageCountDto })
+  @ApiOperation({ summary: '查询未读消息条数' })
+  unreadMessageCount(@Session() session: CommonType.SessionInfo) {
+    return this.messageService.unreadMessageCount(session);
+  }
+
+  /**
+   * @description: 查询未读消息列表
+   */
+  @Get('/unread/list')
+  @ApiOkResponse({ type: UnReadMessageDto })
+  @ApiOperation({ summary: '查询未读消息列表' })
+  getUnreadMessageList(@Query() params: PaginatingDTO, @Session() session: CommonType.SessionInfo) {
+    return this.messageService.getUnreadMessageList(params, session);
+  }
+}

+ 22 - 0
server/src/modules/administrative/message/message.module.ts

@@ -0,0 +1,22 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-09-02 16:10:16
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-09-02 16:10:27
+ * @Description: MessageModule
+ */
+import { Module } from '@nestjs/common';
+
+import { PrismaModule } from '@/modules/prisma/prisma.module';
+import { OperationLogModule } from '@/modules/system-manage/operation-log/operation-log.module';
+
+import { MessageController } from './message.controller';
+import { MessageService } from './message.service';
+
+@Module({
+  imports: [PrismaModule, OperationLogModule],
+  controllers: [MessageController],
+  providers: [MessageService],
+  exports: [MessageService],
+})
+export class MessageModule { }

+ 232 - 0
server/src/modules/administrative/message/message.service.ts

@@ -0,0 +1,232 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-09-02 14:13:35
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-09-09 11:14:21
+ * @Description: MessageService
+ */
+import { Injectable } from '@nestjs/common';
+import type { Message, MessageRead } from '@prisma/client';
+
+import { PaginatingDTO } from '@/dto/params.dto';
+import { PrismaService } from '@/modules/prisma/prisma.service';
+import { responseMessage } from '@/utils';
+
+import { MessageParamsDto } from './dto/params-message.dto';
+import { SaveMessageDto } from './dto/save-message.dto';
+
+@Injectable()
+export class MessageService {
+  constructor(private prisma: PrismaService) { }
+
+  /**
+   * @description: 查询消息公告列表
+   */
+  async findAll({ userId, title, status, startTime, endTime, current, size }: MessageParamsDto) {
+    // 分页处理,这里获取到的分页是字符串,需要转换成整数
+    const take = Number(size);
+    const skip = (Number(current) - 1) * take;
+    // 条件判断
+    const where = {}; // 查询参数
+    // 模糊查询
+    if (userId) {
+      where['userId'] = { equals: userId };
+    }
+
+    if (title) {
+      where['title'] = { contains: title, mode: 'insensitive' };
+    }
+
+    if (status) {
+      where['status'] = { equals: status };
+    }
+
+    if (startTime && endTime) {
+      where['createdAt'] = {
+        gte: new Date(Number(startTime)),
+        lte: new Date(Number(endTime)),
+      };
+    }
+    const records = await this.prisma.message.findMany({
+      skip,
+      take,
+      where,
+      include: {
+        user: true,
+        messageReads: {
+          include: {
+            user: true,
+          },
+        },
+      },
+      orderBy: [
+        { pinned: 'desc' },
+        { createdAt: 'desc' }, // 如果sort相同,再按照createdAt字段降序
+      ],
+    });
+    // 总条数
+    const total = await this.prisma.message.count({ where });
+    return responseMessage<CommonType.PageResponse<Message>>({
+      records,
+      total,
+      current: Number(current),
+      size: take,
+    });
+  }
+
+  /**
+   * @description: 查询单个消息公告
+   */
+  async findOne(id: string) {
+    const result = await this.prisma.message.findUnique({
+      where: {
+        id,
+      },
+      include: {
+        user: true,
+        messageReads: true,
+      },
+    });
+    return responseMessage<Message>(result);
+  }
+
+  /**
+   * @description: 创建消息公告
+   */
+  async create(body: SaveMessageDto, session: CommonType.SessionInfo) {
+    const result = await this.prisma.message.create({
+      data: {
+        ...body,
+        userId: session.userInfo.id,
+      },
+      include: {
+        user: true,
+        messageReads: true,
+      },
+    });
+    return responseMessage<Message>(result);
+  }
+
+  /**
+   * @description: 更新消息公告
+   */
+  async update(id: string, body: SaveMessageDto) {
+    const result = await this.prisma.message.update({
+      where: { id },
+      data: body,
+    });
+    return responseMessage<Message>(result);
+  }
+
+  /**
+   * @description: 删除消息公告
+   */
+  async remove(id: string) {
+    // 开启事务删除
+    const result = await this.prisma.$transaction([
+      this.prisma.messageRead.deleteMany({ where: { messageId: id } }),
+      this.prisma.message.delete({
+        where: { id },
+      }),
+    ]);
+    return responseMessage<[{ count: number }, Message]>(result);
+  }
+
+  /**
+   * @description: 修改置顶状态
+   */
+  async changePinned(id: string) {
+    // 查询当前数据
+    const message = await this.prisma.message.findUnique({
+      where: {
+        id,
+      },
+    });
+    // 更新置顶状态
+    const result = await this.prisma.message.update({
+      where: { id },
+      data: {
+        pinned: !message?.pinned,
+      },
+    });
+    return responseMessage<Message>(result);
+  }
+
+  /**
+   * @description: 创建已读信息
+   */
+  async createMessageRead(id: string, session: CommonType.SessionInfo) {
+    // 查询当前用户是否已读
+    const read = await this.prisma.messageRead.findFirst({
+      where: {
+        messageId: id,
+        userId: session.userInfo.id,
+      },
+    });
+    // 如果有记录,直接返回
+    if (read) {
+      return responseMessage<null>(read);
+    }
+    // 没有记录则新增一条记录
+    const result = await this.prisma.messageRead.create({
+      data: {
+        messageId: id,
+        userId: session.userInfo.id,
+      },
+    });
+    return responseMessage<MessageRead>(result);
+  }
+
+  /**
+   * @description: 查询未读消息条数
+   */
+  async unreadMessageCount(session: CommonType.SessionInfo) {
+    // 查询未读消息条数
+    const result = await this.prisma.message.count({
+      where: {
+        NOT: {
+          messageReads: {
+            some: {
+              userId: session.userInfo.id,
+            },
+          },
+        },
+      },
+    });
+    return responseMessage<number>(result);
+  }
+
+  /**
+   * @description: 查询未读消息列表
+   */
+  async getUnreadMessageList({ current, size }: PaginatingDTO, session: CommonType.SessionInfo) {
+    // 分页处理,这里获取到的分页是字符串,需要转换成整数
+    const take = Number(size);
+    const skip = (Number(current) - 1) * take;
+    // 查询未读消息条数
+    const result = await this.prisma.message.findMany({
+      skip,
+      take,
+      where: {
+        messageReads: {
+          none: {
+            userId: session.userInfo.id,
+          },
+        },
+      },
+      include: {
+        user: true,
+        messageReads: {
+          include: {
+            user: true,
+          },
+        },
+      },
+      orderBy: [
+        { pinned: 'desc' },
+        { createdAt: 'desc' }, // 如果sort相同,再按照createdAt字段降序
+      ],
+    });
+    return responseMessage<Message[]>(result);
+  }
+}

+ 27 - 0
server/src/modules/administrative/organazation/dto/params-organazation.dto.ts

@@ -0,0 +1,27 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-11 16:44:40
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-07-16 10:28:13
+ * @Description: 请求参数 DTO
+ */
+
+import { ApiProperty } from '@nestjs/swagger';
+
+export class OrganazationParamsDto {
+  @ApiProperty({
+    type: String,
+    description: '组织名称',
+    required: false,
+    default: '阿里巴巴',
+  })
+  name?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '组织编码',
+    required: false,
+    default: 'Alibaba',
+  })
+  code?: string;
+}

+ 59 - 0
server/src/modules/administrative/organazation/dto/response-organazation.dto.ts

@@ -0,0 +1,59 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-11 16:19:40
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-22 15:13:48
+ * @Description: 响应体
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import type { Organization } from '@prisma/client';
+
+import { ResponseDto } from '@/dto/response.dto';
+
+/**
+ * @description: 组织管理列表响应体结构 Dto
+ */
+export class ResponseOrganizationDto extends ResponseDto {
+  @ApiProperty({
+    type: Array,
+    description: '响应体',
+    default: {
+      records: [
+        {
+          id: '1db25530-7407-45ad-ad47-e9dda010e5e8',
+          name: '阿里巴巴',
+          code: 'ALI_001',
+          parentId: null,
+          sort: 1,
+          description:
+            '阿里巴巴集团控股有限公司(简称:阿里巴巴集团)是马云带领下的18位创始人于1999年在浙江省杭州市创立的公司。',
+          createdAt: '2024-07-11T08:30:52.100Z',
+          updatedAt: '2024-07-11T08:30:52.100Z',
+        },
+      ],
+    },
+  })
+  data: Organization[];
+}
+
+/**
+ * @description: 创建/更新/删除组织数据 Dto
+ */
+export class ResponseSaveOrganizationDto extends ResponseDto {
+  @ApiProperty({
+    type: Object,
+    description: '响应体',
+    default: {
+      id: '1db25530-7407-45ad-ad47-e9dda010e5e8',
+      name: '阿里巴巴',
+      code: 'ALI_001',
+      parentId: null,
+      sort: 1,
+      description:
+        '阿里巴巴集团控股有限公司(简称:阿里巴巴集团)是马云带领下的18位创始人于1999年在浙江省杭州市创立的公司。',
+      createdAt: '2024-07-11T08:30:52.100Z',
+      updatedAt: '2024-07-11T08:30:52.100Z',
+    },
+  })
+  data: Organization;
+}

+ 58 - 0
server/src/modules/administrative/organazation/dto/save-organazation.dto.ts

@@ -0,0 +1,58 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-10 13:39:42
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-22 11:40:09
+ * @Description: 保存组织数据 Dto
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { IsNotEmpty, IsNumber, IsOptional, IsUUID } from 'class-validator';
+
+export class SaveOrganazationDto {
+  @ApiProperty({
+    type: String,
+    description: '父级id',
+    default: '0c01ef7d-2f6f-440a-b642-62564d41f473',
+    required: false,
+  })
+  @IsOptional()
+  @IsUUID('all', { message: 'parentId 参数不正确' })
+  parentId?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '组织名称',
+    default: '阿里巴巴',
+  })
+  @IsNotEmpty({ message: '组织名称必填' })
+  name: string;
+
+  @ApiProperty({
+    type: String,
+    description: '组织编码',
+    default: 'Alibaba',
+  })
+  @IsNotEmpty({ message: '组织岗位必填' })
+  code: string;
+
+  @ApiProperty({
+    type: Number,
+    description: '排序',
+    default: 1,
+  })
+  @IsNumber(
+    {},
+    {
+      message: '排序必须为数字',
+    },
+  )
+  sort: number;
+
+  @ApiProperty({
+    type: String,
+    description: '组织描述',
+    required: false,
+    default: '阿里巴巴集团控股有限公司(简称:阿里巴巴集团)是马云带领下的18位创始人于1999年在浙江省杭州市创立的公司。',
+  })
+  description?: string;
+}

+ 93 - 0
server/src/modules/administrative/organazation/organazation.controller.ts

@@ -0,0 +1,93 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-10 13:39:42
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-26 09:00:47
+ * @Description: OrganazationController
+ */
+import {
+  Body,
+  Controller,
+  Delete,
+  Get,
+  Param,
+  ParseUUIDPipe,
+  Post,
+  Put,
+  Query,
+  UseGuards,
+  UseInterceptors,
+} from '@nestjs/common';
+import { AuthGuard } from '@nestjs/passport';
+import { ApiBearerAuth, ApiHeader, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; // swagger 接口文档
+
+import { LoggerInterceptor } from '@/interceptor/logger.interceptor';
+
+import { OrganazationParamsDto } from './dto/params-organazation.dto';
+import { ResponseOrganizationDto, ResponseSaveOrganizationDto } from './dto/response-organazation.dto';
+import { SaveOrganazationDto } from './dto/save-organazation.dto';
+import { OrganazationService } from './organazation.service';
+
+@ApiTags('智能行政-组织管理')
+@ApiHeader({
+  name: 'Authorization',
+  required: true,
+  description: 'token令牌',
+})
+@ApiBearerAuth()
+@Controller('administrative/organazation')
+@UseInterceptors(LoggerInterceptor)
+@UseGuards(AuthGuard('jwt'))
+export class OrganazationController {
+  constructor(private readonly organazationService: OrganazationService) { }
+
+  /**
+   * @description: 查询组织列表
+   */
+  @Get()
+  @ApiOkResponse({ type: ResponseOrganizationDto })
+  @ApiOperation({ summary: '获取组织管理列表' })
+  findAll(@Query() params: OrganazationParamsDto) {
+    return this.organazationService.findAll(params);
+  }
+
+  /**
+   * @description: 创建组织
+   */
+  @Post()
+  @ApiOkResponse({ type: ResponseSaveOrganizationDto })
+  @ApiOperation({ summary: '创建组织' })
+  create(@Body() body: SaveOrganazationDto) {
+    return this.organazationService.create(body);
+  }
+
+  /**
+   * @description: 查询组织详情
+   */
+  @Get(':id')
+  @ApiOkResponse({ type: ResponseSaveOrganizationDto })
+  @ApiOperation({ summary: '查询组织详情' })
+  findOne(@Param('id', new ParseUUIDPipe()) id: string) {
+    return this.organazationService.findOne(id);
+  }
+
+  /**
+   * @description: 更新组织
+   */
+  @Put(':id')
+  @ApiOkResponse({ type: ResponseSaveOrganizationDto })
+  @ApiOperation({ summary: '更新组织' })
+  update(@Param('id', new ParseUUIDPipe()) id: string, @Body() body: SaveOrganazationDto) {
+    return this.organazationService.update(id, body);
+  }
+
+  /**
+   * @description: 删除组织
+   */
+  @Delete(':id')
+  @ApiOkResponse({ type: ResponseSaveOrganizationDto })
+  @ApiOperation({ summary: '删除组织' })
+  remove(@Param('id', new ParseUUIDPipe()) id: string) {
+    return this.organazationService.remove(id);
+  }
+}

+ 22 - 0
server/src/modules/administrative/organazation/organazation.module.ts

@@ -0,0 +1,22 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-12 14:34:56
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-07 10:01:22
+ * @Description: OrganazationModule
+ */
+import { Module } from '@nestjs/common';
+
+import { PrismaModule } from '@/modules/prisma/prisma.module';
+import { OperationLogModule } from '@/modules/system-manage/operation-log/operation-log.module';
+
+import { OrganazationController } from './organazation.controller';
+import { OrganazationService } from './organazation.service';
+
+@Module({
+  imports: [PrismaModule, OperationLogModule],
+  controllers: [OrganazationController],
+  providers: [OrganazationService],
+  exports: [OrganazationService],
+})
+export class OrganazationModule { }

+ 127 - 0
server/src/modules/administrative/organazation/organazation.service.ts

@@ -0,0 +1,127 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-10 13:39:42
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-22 15:42:28
+ * @Description: OrganazationService - 组织管理
+ */
+import { Injectable } from '@nestjs/common';
+import type { Organization } from '@prisma/client';
+
+import { RESPONSE_MSG } from '@/enums';
+import { PrismaService } from '@/modules/prisma/prisma.service';
+import { convertFlatDataToTree, responseMessage } from '@/utils';
+
+import { OrganazationParamsDto } from './dto/params-organazation.dto';
+import { SaveOrganazationDto } from './dto/save-organazation.dto';
+
+@Injectable()
+export class OrganazationService {
+  constructor(private prisma: PrismaService) { }
+
+  /**
+   * @description: 查询组织列表
+   */
+  async findAll({ name, code }: OrganazationParamsDto) {
+    // 条件判断
+    const where = {}; // 查询参数
+    // 模糊查询
+    if (name) {
+      where['name'] = { contains: name, mode: 'insensitive' };
+    }
+
+    if (code) {
+      where['code'] = { contains: code, mode: 'insensitive' };
+    }
+    const result = await this.prisma.organization.findMany({
+      where,
+      include: {
+        posts: true,
+      },
+      orderBy: [
+        { sort: 'asc' }, // 按照sort字段升序
+        { createdAt: 'desc' }, // 如果sort相同,再按照createdAt字段降序
+      ],
+    });
+    return responseMessage<CommonType.PageResponse<Organization>>({
+      records: convertFlatDataToTree(result),
+    });
+  }
+
+  /**
+   * @description: 查询单个组织
+   */
+  async findOne(id: string) {
+    const result = await this.prisma.organization.findUnique({
+      where: {
+        id,
+      },
+    });
+    return responseMessage<Organization>(result);
+  }
+
+  /**
+   * @description: 创建组织
+   */
+  async create(body: SaveOrganazationDto) {
+    try {
+      const result = await this.prisma.organization.create({
+        data: body,
+      });
+      return responseMessage<Organization>(result);
+    } catch (error) {
+      // 判断是否违反 postgresql 唯一性约束
+      if (error.code === 'P2002') {
+        return responseMessage(null, '组织名称或编码已存在!', -1);
+      }
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 更新组织
+   */
+  async update(id: string, body: SaveOrganazationDto) {
+    try {
+      // 判断父级不能是子级
+      if (id === body.parentId) {
+        return responseMessage(null, '父级不能是自己!', -1);
+      }
+      const result = await this.prisma.organization.update({
+        where: { id },
+        data: body,
+      });
+      return responseMessage<Organization>(result);
+    } catch (error) {
+      // 判断是否违反 postgresql 唯一性约束
+      if (error.code === 'P2002') {
+        return responseMessage(null, '组织名称或编码已存在!', -1);
+      }
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 删除组织
+   */
+  async remove(id: string) {
+    try {
+      // 查询该组织是否有子组织
+      const hasChildren = await this.prisma.organization.count({
+        where: {
+          parentId: id,
+        },
+      });
+      if (hasChildren > 0) {
+        return responseMessage(null, '该组织下有子级,不能删除!', -1);
+      } else {
+        const result = await this.prisma.organization.delete({
+          where: { id },
+        });
+        return responseMessage<Organization>(result);
+      }
+    } catch (error) {
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+}

+ 50 - 0
server/src/modules/administrative/post-manage/dto/params-post.dto.ts

@@ -0,0 +1,50 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-11 16:44:40
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-07-17 15:23:42
+ * @Description: 请求参数 DTO
+ */
+
+import { ApiProperty } from '@nestjs/swagger';
+import { IsNumberString, IsOptional, IsUUID } from 'class-validator';
+
+export class PostParamsDto {
+  @ApiProperty({
+    type: String,
+    description: '岗位名称',
+    required: false,
+    default: '前端工程师',
+  })
+  name?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '所属组织',
+    default: 'f45cd48b-e703-49db-91be-ae7f594e73e0',
+    required: false,
+  })
+  @IsOptional()
+  @IsUUID('all', { message: 'orgId 参数不正确' })
+  orgId?: string;
+
+  @ApiProperty({
+    type: Number,
+    description: '开始日期',
+    default: 1721145600000,
+    required: false,
+  })
+  @IsOptional()
+  @IsNumberString({}, { message: '开始日期必须是时间戳格式' })
+  startTime?: number;
+
+  @ApiProperty({
+    type: Number,
+    description: '结束日期',
+    default: 1721318399999,
+    required: false,
+  })
+  @IsOptional()
+  @IsNumberString({}, { message: '结束日期必须是时间戳格式' })
+  endTime?: number;
+}

+ 96 - 0
server/src/modules/administrative/post-manage/dto/response-post.dto.ts

@@ -0,0 +1,96 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-11 16:19:40
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-22 15:17:28
+ * @Description: 响应体
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import type { Post } from '@prisma/client';
+
+import { ResponseDto } from '@/dto/response.dto';
+
+/**
+ * @description: 岗位管理列表响应体结构 Dto
+ */
+export class ResponsePostDto extends ResponseDto {
+  @ApiProperty({
+    type: Array,
+    description: '响应体',
+    default: {
+      records: [
+        {
+          id: '1d83e15c-3dba-4cbf-bd23-e1f37b3ab834',
+          name: '程序员',
+          orgId: 'f45cd48b-e703-49db-91be-ae7f594e73e0',
+          parentId: null,
+          sort: 1,
+          description:
+            '程序员(英文Programmer)是从事程序开发、程序维护的基层工作人员。一般将程序员分为程序设计人员和程序编码人员,但两者的界限并不非常清楚。随着互联网的不断普及,网络上把男程序员称作“程序猿”。或将男女程序员统称为“工程师(攻城狮)”。',
+          createdAt: '2024-07-17T00:39:54.384Z',
+          updatedAt: '2024-07-17T01:36:06.188Z',
+          organization: {
+            id: 'f45cd48b-e703-49db-91be-ae7f594e73e0',
+            name: '阿里巴巴',
+            code: 'ALI_000',
+            parentId: null,
+            sort: 1,
+            description:
+              '阿里巴巴集团由曾担任英语教师的马云为首的18人,于1999年在中国杭州创立。从一开始,所有创始人就深信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。自推出让中国的小型出口商、制造商及创业者接触全球买家的首个网站以来,阿里巴巴集团不断成长,成为了网上及移动商务的全球领导者。',
+            icon: 'simple-icons:alibabadotcom',
+            createdAt: '2024-07-15T07:59:08.613Z',
+            updatedAt: '2024-07-15T07:59:08.613Z',
+          },
+          children: [
+            {
+              id: '34f2d5e1-7378-46b3-8f0c-56cfdbb8f3eb',
+              name: '前端工程师',
+              orgId: '9382c3d0-42ef-496b-961f-f0bcee6edfbf',
+              parentId: '1d83e15c-3dba-4cbf-bd23-e1f37b3ab834',
+              sort: 1,
+              description:
+                '前端工程师是互联网时代软件产品研发中不可缺少的一种专业研发角色。从狭义上讲,前端工程师使用 HTML、CSS、JavaScript 等专业技能和工具将产品UI设计稿实现成网站产品,涵盖用户PC端、移动端网页,处理视觉和交互问题。从广义上来讲,所有用户终端产品与视觉和交互有关的部分,都是前端工程师的专业领域。',
+              createdAt: '2024-07-17T01:02:27.831Z',
+              updatedAt: '2024-07-17T01:02:27.831Z',
+              organization: {
+                id: '9382c3d0-42ef-496b-961f-f0bcee6edfbf',
+                name: '支付宝',
+                code: 'ALI_002',
+                parentId: 'f45cd48b-e703-49db-91be-ae7f594e73e0',
+                sort: 1,
+                description:
+                  '支付宝(Alipay)是蚂蚁科技集团股份有限公司旗下业务,成立于2004年,是中国第三方支付开放平台,是当下世界上流行的网络银行和网络支付形式之一。',
+                icon: 'ri:alipay-fill',
+                createdAt: '2024-07-15T07:59:53.677Z',
+                updatedAt: '2024-07-15T07:59:53.677Z',
+              },
+            },
+          ],
+        },
+      ],
+    },
+  })
+  data: Post[];
+}
+
+/**
+ * @description: 创建/更新/删除岗位数据 Dto
+ */
+export class ResponseSavePostDto extends ResponseDto {
+  @ApiProperty({
+    type: Object,
+    description: '响应体',
+    default: {
+      id: '34f2d5e1-7378-46b3-8f0c-56cfdbb8f3eb',
+      name: '前端工程师',
+      orgId: '9382c3d0-42ef-496b-961f-f0bcee6edfbf',
+      parentId: '1d83e15c-3dba-4cbf-bd23-e1f37b3ab834',
+      sort: 1,
+      description:
+        '前端工程师是互联网时代软件产品研发中不可缺少的一种专业研发角色。从狭义上讲,前端工程师使用 HTML、CSS、JavaScript 等专业技能和工具将产品UI设计稿实现成网站产品,涵盖用户PC端、移动端网页,处理视觉和交互问题。从广义上来讲,所有用户终端产品与视觉和交互有关的部分,都是前端工程师的专业领域。',
+      createdAt: '2024-07-17T01:02:27.831Z',
+      updatedAt: '2024-07-17T01:02:27.831Z',
+    },
+  })
+  data: Post;
+}

+ 59 - 0
server/src/modules/administrative/post-manage/dto/save-post.dto.ts

@@ -0,0 +1,59 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-10 13:39:42
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-07-17 15:19:57
+ * @Description: 保存岗位数据 Dto
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { IsNotEmpty, IsNumber, IsOptional, IsUUID } from 'class-validator';
+
+export class SavePostDto {
+  @ApiProperty({
+    type: String,
+    description: '父级id',
+    default: '0c01ef7d-2f6f-440a-b642-62564d41f473',
+    required: false,
+  })
+  @IsOptional()
+  @IsUUID('all', { message: 'parentId 参数不正确' })
+  parentId?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '岗位名称',
+    default: '前端工程师',
+  })
+  @IsNotEmpty({ message: '岗位名称必填' })
+  name: string;
+
+  @ApiProperty({
+    type: String,
+    description: '组织id',
+    default: 'f45cd48b-e703-49db-91be-ae7f594e73e0',
+  })
+  @IsUUID('all', { message: 'orgId 参数不正确' })
+  orgId: string;
+
+  @ApiProperty({
+    type: Number,
+    description: '排序',
+    default: 1,
+  })
+  @IsNumber(
+    {},
+    {
+      message: '排序必须为数字',
+    },
+  )
+  sort: number;
+
+  @ApiProperty({
+    type: String,
+    description: '岗位描述',
+    default:
+      '前端工程师是互联网时代软件产品研发中不可缺少的一种专业研发角色。从狭义上讲,前端工程师使用 HTML、CSS、JavaScript 等专业技能和工具将产品UI设计稿实现成网站产品,涵盖用户PC端、移动端网页,处理视觉和交互问题。',
+    required: false,
+  })
+  description?: string;
+}

+ 93 - 0
server/src/modules/administrative/post-manage/post-manage.controller.ts

@@ -0,0 +1,93 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-10 13:39:42
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-26 09:01:14
+ * @Description: PostManageController
+ */
+import {
+  Body,
+  Controller,
+  Delete,
+  Get,
+  Param,
+  ParseUUIDPipe,
+  Post,
+  Put,
+  Query,
+  UseGuards,
+  UseInterceptors,
+} from '@nestjs/common';
+import { AuthGuard } from '@nestjs/passport';
+import { ApiBearerAuth, ApiHeader, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; // swagger 接口文档
+
+import { LoggerInterceptor } from '@/interceptor/logger.interceptor';
+
+import { PostParamsDto } from './dto/params-post.dto';
+import { ResponsePostDto, ResponseSavePostDto } from './dto/response-post.dto';
+import { SavePostDto } from './dto/save-post.dto';
+import { PostManageService } from './post-manage.service';
+
+@ApiTags('智能行政-岗位管理')
+@ApiHeader({
+  name: 'Authorization',
+  required: true,
+  description: 'token令牌',
+})
+@ApiBearerAuth()
+@Controller('administrative/post-manage')
+@UseInterceptors(LoggerInterceptor)
+@UseGuards(AuthGuard('jwt'))
+export class PostManageController {
+  constructor(private readonly postManageService: PostManageService) { }
+
+  /**
+   * @description: 查询岗位列表
+   */
+  @Get()
+  @ApiOkResponse({ type: ResponsePostDto })
+  @ApiOperation({ summary: '获取岗位管理列表' })
+  findAll(@Query() params: PostParamsDto) {
+    return this.postManageService.findAll(params);
+  }
+
+  /**
+   * @description: 创建岗位
+   */
+  @Post()
+  @ApiOkResponse({ type: ResponseSavePostDto })
+  @ApiOperation({ summary: '创建岗位' })
+  create(@Body() body: SavePostDto) {
+    return this.postManageService.create(body);
+  }
+
+  /**
+   * @description: 查询岗位详情
+   */
+  @Get(':id')
+  @ApiOkResponse({ type: ResponseSavePostDto })
+  @ApiOperation({ summary: '查询岗位详情' })
+  findOne(@Param('id', new ParseUUIDPipe()) id: string) {
+    return this.postManageService.findOne(id);
+  }
+
+  /**
+   * @description: 更新岗位
+   */
+  @Put(':id')
+  @ApiOkResponse({ type: ResponseSavePostDto })
+  @ApiOperation({ summary: '更新岗位' })
+  update(@Param('id', new ParseUUIDPipe()) id: string, @Body() body: SavePostDto) {
+    return this.postManageService.update(id, body);
+  }
+
+  /**
+   * @description: 删除岗位
+   */
+  @Delete(':id')
+  @ApiOkResponse({ type: ResponseSavePostDto })
+  @ApiOperation({ summary: '删除岗位' })
+  remove(@Param('id', new ParseUUIDPipe()) id: string) {
+    return this.postManageService.remove(id);
+  }
+}

+ 22 - 0
server/src/modules/administrative/post-manage/post-manage.module.ts

@@ -0,0 +1,22 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-12 14:34:56
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-07-16 16:20:21
+ * @Description: PostManageModule
+ */
+import { Module } from '@nestjs/common';
+
+import { PrismaModule } from '@/modules/prisma/prisma.module';
+import { OperationLogModule } from '@/modules/system-manage/operation-log/operation-log.module';
+
+import { PostManageController } from './post-manage.controller';
+import { PostManageService } from './post-manage.service';
+
+@Module({
+  imports: [PrismaModule, OperationLogModule],
+  controllers: [PostManageController],
+  providers: [PostManageService],
+  exports: [PostManageService],
+})
+export class PostManageModule { }

+ 135 - 0
server/src/modules/administrative/post-manage/post-manage.service.ts

@@ -0,0 +1,135 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-16 15:40:07
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-22 15:42:55
+ * @Description: PostManageService - 岗位管理
+ */
+
+import { Injectable } from '@nestjs/common';
+import type { Post } from '@prisma/client';
+
+import { RESPONSE_MSG } from '@/enums';
+import { PrismaService } from '@/modules/prisma/prisma.service';
+import { convertFlatDataToTree, responseMessage } from '@/utils';
+
+import { PostParamsDto } from './dto/params-post.dto';
+import { SavePostDto } from './dto/save-post.dto';
+
+@Injectable()
+export class PostManageService {
+  constructor(private prisma: PrismaService) { }
+
+  /**
+   * @description: 查询岗位列表
+   */
+  async findAll({ name, orgId, startTime, endTime }: PostParamsDto) {
+    // 条件判断
+    const where = {}; // 查询参数
+    // 模糊查询
+    if (name) {
+      where['name'] = { contains: name, mode: 'insensitive' };
+    }
+
+    if (orgId) {
+      where['orgId'] = { equals: orgId };
+    }
+
+    if (startTime && endTime) {
+      where['createdAt'] = {
+        gte: new Date(Number(startTime)),
+        lte: new Date(Number(endTime)),
+      };
+    }
+    const result = await this.prisma.post.findMany({
+      where,
+      include: {
+        organization: true,
+      },
+      orderBy: [
+        { sort: 'asc' }, // 按照sort字段升序
+        { createdAt: 'desc' }, // 如果sort相同,再按照createdAt字段降序
+      ],
+    });
+    return responseMessage<CommonType.PageResponse<Post>>({
+      records: convertFlatDataToTree(result),
+    });
+  }
+
+  /**
+   * @description: 查询单个岗位信息
+   */
+  async findOne(id: string) {
+    const result = await this.prisma.post.findUnique({
+      where: {
+        id,
+      },
+    });
+    return responseMessage<Post>(result);
+  }
+
+  /**
+   * @description: 创建岗位
+   */
+  async create(body: SavePostDto) {
+    try {
+      const result = await this.prisma.post.create({
+        data: body,
+      });
+      return responseMessage<Post>(result);
+    } catch (error) {
+      // 判断是否违反 postgresql 唯一性约束
+      if (error.code === 'P2002') {
+        return responseMessage(null, '岗位名称已存在!', -1);
+      }
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 更新岗位
+   */
+  async update(id: string, body: SavePostDto) {
+    try {
+      // 判断父级不能是子级
+      if (id === body.parentId) {
+        return responseMessage(null, '父级不能是自己!', -1);
+      }
+      const result = await this.prisma.post.update({
+        where: { id },
+        data: body,
+      });
+      return responseMessage<Post>(result);
+    } catch (error) {
+      // 判断是否违反 postgresql 唯一性约束
+      if (error.code === 'P2002') {
+        return responseMessage(null, '岗位名称已存在!', -1);
+      }
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 删除岗位
+   */
+  async remove(id: string) {
+    try {
+      // 查询该岗位是否有子级
+      const hasChildren = await this.prisma.post.count({
+        where: {
+          parentId: id,
+        },
+      });
+      if (hasChildren > 0) {
+        return responseMessage(null, '该岗位下有子级,不能删除!', -1);
+      } else {
+        const result = await this.prisma.post.delete({
+          where: { id },
+        });
+        return responseMessage<Post>(result);
+      }
+    } catch (error) {
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+}

+ 197 - 0
server/src/modules/auth/auth.controller.ts

@@ -0,0 +1,197 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-11 10:01:43
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-10-09 11:01:22
+ * @Description: AuthController
+ */
+import { Body, Controller, Get, Post, Query, Req, Res, Session, UseGuards, UseInterceptors } from '@nestjs/common';
+import { AuthGuard } from '@nestjs/passport';
+import { ApiBearerAuth, ApiHeader, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; // swagger 接口文档
+import { Request, Response } from 'express';
+import svgCaptcha from 'svg-captcha';
+
+import { ResponseDto } from '@/dto/response.dto';
+import { LoggerInterceptor } from '@/interceptor/logger.interceptor';
+import { getRealIp, responseMessage } from '@/utils';
+
+import { AuthService } from './auth.service';
+import { juejinParamsDto, LoginParamsDto, RouteExistParamsDto } from './dto/params-auth.dto';
+import {
+  ConstantRoutesResponseDto,
+  JuejinResponseDto,
+  LocalesResponseDto,
+  LoginResponseDto,
+  RouteExistResponseDto,
+  UserInfoResponseDto,
+  UserRoutesResponseDto,
+  VerifyCodeResponseDto,
+} from './dto/response-auth.dto';
+
+@ApiTags('身份鉴权')
+@Controller('auth')
+@UseInterceptors(LoggerInterceptor)
+export class AuthController {
+  constructor(private readonly authService: AuthService) { }
+  /**
+   * @description: 用户登录
+   */
+  @Post('/login')
+  @ApiOkResponse({ type: LoginResponseDto })
+  @ApiOperation({ summary: '用户登录' })
+  login(@Body() body: LoginParamsDto, @Session() session: CommonType.SessionInfo, @Req() req: Request) {
+    return this.authService.login(body, session, getRealIp(req));
+  }
+
+  /**
+   * @description: 获取用户信息
+   */
+  @UseGuards(AuthGuard('jwt'))
+  @ApiHeader({
+    name: 'Authorization',
+    required: true,
+    description: 'token令牌',
+  })
+  @ApiBearerAuth()
+  @Get('/getUserInfo')
+  @ApiOkResponse({ type: UserInfoResponseDto })
+  @ApiOperation({ summary: '获取用户信息' })
+  getUserInfo(@Session() session: CommonType.SessionInfo) {
+    return this.authService.getUserInfo(session);
+  }
+
+  /**
+   * @description: 用户注销登录
+   */
+  @UseGuards(AuthGuard('jwt'))
+  @ApiHeader({
+    name: 'Authorization',
+    required: true,
+    description: 'token令牌',
+  })
+  @ApiBearerAuth()
+  @Post('/logout')
+  @ApiOkResponse({ type: ResponseDto })
+  @ApiOperation({ summary: '注销登录' })
+  async logout(@Session() session: CommonType.SessionInfo) {
+    const response = await this.authService.logout(session);
+    return response;
+  }
+
+  /**
+   * @description: 获取图形验证码
+   */
+  @Get('captcha') //当请求该接口时,返回一张随机图片验证码
+  @ApiOkResponse({ type: VerifyCodeResponseDto })
+  @ApiOperation({ summary: '获取图形验证码' })
+  async getCaptcha(@Session() session: CommonType.SessionInfo, @Res() res: Response) {
+    const captcha = svgCaptcha.createMathExpr({
+      //可配置返回的图片信息
+      size: 4, // 验证码长度
+      ignoreChars: '0oO1ilI', // 验证码字符中排除 0oO1ilI
+      noise: 2, // 干扰线条的数量
+      width: 132,
+      height: 40,
+      fontSize: 50,
+      color: true, // 验证码的字符是否有颜色,默认没有,如果设定了背景,则默认有
+      background: '#fff',
+    });
+    session.captchaCode = captcha.text; //使用session保存验证,用于登陆时验证
+    res.type('image/svg+xml'); //指定返回的类型
+    return res.send(responseMessage(captcha.data)); //给页面返回一张图片
+  }
+
+  /**
+   * @description: 国际化层级数据
+   */
+  @Get('/getLocales')
+  @ApiOkResponse({ type: LocalesResponseDto })
+  @ApiOperation({ summary: '国际化层级数据' })
+  async getLocales() {
+    const response = await this.authService.getLocales();
+    return response;
+  }
+
+  /**
+   * @description: 获取掘金文章列表
+   */
+  @UseGuards(AuthGuard('jwt'))
+  @ApiHeader({
+    name: 'Authorization',
+    required: true,
+    description: 'token令牌',
+  })
+  @ApiBearerAuth()
+  @Post('/juejin')
+  @ApiOkResponse({ type: JuejinResponseDto })
+  @ApiOperation({ summary: '获取掘金文章列表' })
+  async juejin(@Body() params: juejinParamsDto) {
+    const response = await this.authService.juejin(params);
+    return response;
+  }
+
+  /**
+   * @description: 获取动态路由表
+   */
+  @Get('/getConstantRoutes')
+  @ApiOkResponse({ type: ConstantRoutesResponseDto })
+  @ApiOperation({ summary: '获取常量路由' })
+  getConstantRoutes() {
+    const response = this.authService.getConstantRoutes();
+    return response;
+  }
+
+  /**
+   * @description: 获取用户路由
+   */
+  @UseGuards(AuthGuard('jwt'))
+  @ApiHeader({
+    name: 'Authorization',
+    required: true,
+    description: 'token令牌',
+  })
+  @ApiBearerAuth()
+  @Get('/getUserRoutes')
+  @ApiOkResponse({ type: UserRoutesResponseDto })
+  @ApiOperation({ summary: '获取用户路由' })
+  getUserRoutes(@Session() session: CommonType.SessionInfo) {
+    const response = this.authService.getUserRoutes(session);
+    return response;
+  }
+
+  /**
+   * @description: 判断路由名称是否存在
+   */
+  @UseGuards(AuthGuard('jwt'))
+  @ApiHeader({
+    name: 'Authorization',
+    required: true,
+    description: 'token令牌',
+  })
+  @ApiBearerAuth()
+  @Get('/isRouteExist')
+  @ApiOkResponse({ type: RouteExistResponseDto })
+  @ApiOperation({ summary: '判断路由名称是否存在' })
+  isRouteExist(@Query() params: RouteExistParamsDto) {
+    const response = this.authService.isRouteExist(params.name);
+    return response;
+  }
+
+  /**
+   * @description: 获取角色权限路由
+   */
+  @UseGuards(AuthGuard('jwt'))
+  @ApiHeader({
+    name: 'Authorization',
+    required: true,
+    description: 'token令牌',
+  })
+  @ApiBearerAuth()
+  @Get('/getRoleRoutes')
+  @ApiOkResponse({ type: UserRoutesResponseDto })
+  @ApiOperation({ summary: '获取角色权限路由' })
+  getRoleRoutes() {
+    const response = this.authService.getRoleRoutes();
+    return response;
+  }
+}

+ 38 - 0
server/src/modules/auth/auth.module.ts

@@ -0,0 +1,38 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-11 10:04:27
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-16 17:01:44
+ * @Description: AuthModule
+ */
+import { HttpModule } from '@nestjs/axios';
+import { Module } from '@nestjs/common';
+import { JwtModule } from '@nestjs/jwt';
+import { PassportModule } from '@nestjs/passport';
+
+import { PrismaModule } from '@/modules/prisma/prisma.module';
+import { OperationLogModule } from '@/modules/system-manage/operation-log/operation-log.module';
+
+import { AuthController } from './auth.controller';
+import { AuthService } from './auth.service';
+import { JwtStrategy } from './jwt.strategy';
+
+@Module({
+  imports: [
+    PrismaModule,
+    PassportModule.register({ defaultStrategy: 'jwt' }),
+    JwtModule.register({
+      secret: process.env.JWT_SECRET,
+      signOptions: { expiresIn: '15m' }, // 这里设置访问 token 的过期时间
+    }),
+    HttpModule.register({
+      timeout: 5000,
+      maxRedirects: 5,
+    }),
+    OperationLogModule,
+  ],
+  controllers: [AuthController],
+  providers: [AuthService, JwtStrategy],
+  exports: [AuthService],
+})
+export class AuthModule { }

+ 328 - 0
server/src/modules/auth/auth.service.ts

@@ -0,0 +1,328 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-11 09:59:05
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-09-09 17:23:59
+ * @Description: AuthService
+ */
+import { HttpService } from '@nestjs/axios';
+import { Injectable } from '@nestjs/common';
+import { JwtService } from '@nestjs/jwt';
+import { type Menu, MenuType, Status, type User } from '@prisma/client';
+import * as bcrypt from 'bcryptjs';
+import { lastValueFrom, map } from 'rxjs';
+
+import { PrismaService } from '@/modules/prisma/prisma.service';
+import { convertFlatDataToTree, convertToLocalization, omit, responseMessage } from '@/utils';
+
+import { juejinParamsDto, LoginParamsDto } from './dto/params-auth.dto';
+
+@Injectable()
+export class AuthService {
+  constructor(
+    private prisma: PrismaService,
+    private readonly jwtService: JwtService,
+    private readonly httpService: HttpService,
+  ) {}
+  /**
+   * @description: 用户登录
+   */
+  async login(params: LoginParamsDto, session: CommonType.SessionInfo, ip: string) {
+    // 获取验证码
+    const { captchaCode } = params;
+    // 判断验证码
+    if (captchaCode.toUpperCase() !== session.captchaCode.toUpperCase()) {
+      return responseMessage(null, '验证码错误', -1);
+    }
+    // 登录参数校验结果
+    const user = await this.validateUser(params);
+
+    if (!user) {
+      return responseMessage(null, '用户名或密码错误', -1);
+    }
+
+    // 判断用户是否禁用
+    if (user.status === Status.INACTIVE) {
+      return responseMessage(null, '该用户已被禁用', -1);
+    }
+
+    // 生成 token
+    const tokens = await this.generateTokens(user);
+
+    // 登录成功,更新用户信息
+    const userInfo = await this.prisma.user.update({
+      where: { id: user.id },
+      data: {
+        loginCount: { increment: 1 }, // 登录次数 + 1
+        lastLoginAt: new Date(),
+        lastIp: ip,
+        token: tokens.token,
+      },
+      include: {
+        role: true,
+        // organization: true,
+        // post: true,
+      },
+    });
+
+    // 存储用户信息到 session
+    session.userInfo = userInfo;
+
+    // 验证成功,返回 token
+    return responseMessage<Pick<User, 'token'>>(tokens);
+  }
+
+  /**
+   * @description: 获取用户信息
+   */
+  async getUserInfo(session: CommonType.SessionInfo) {
+    // 获取 session 用户信息
+    const userInfo = omit(session.userInfo, ['password', 'token']);
+    // 获取所有与 roleId 相关的 menuId
+    const menuIds = await this.prisma.permission
+      .findMany({
+        where: {
+          roleId: userInfo.roleId,
+        },
+        select: {
+          menuId: true,
+        },
+      })
+      .then((results) => results.map((result) => result.menuId));
+    // 使用这些 menuId 查询 Menu 模型
+    const permissions = await this.prisma.menu
+      .findMany({
+        where: {
+          type: {
+            equals: MenuType.BUTTON,
+          },
+          id: {
+            in: menuIds,
+          },
+        },
+      })
+      .then((results) => results.map((result) => result.permission));
+    return responseMessage<User>({
+      ...userInfo,
+      buttons: permissions,
+      roles: [userInfo.role.code],
+    });
+  }
+
+  /**
+   * @description: 验证用户登录
+   */
+  async validateUser(params: LoginParamsDto): Promise<User | null> {
+    // 解构参数
+    const { userName, password } = params;
+
+    // 查询数据库中对应的用户
+    const userInfo = await this.prisma.user.findUnique({
+      where: { userName },
+    });
+    if (userInfo && (await this.comparePassword(password, userInfo.password))) {
+      // 如果用户名密码正确,则返回用户对象
+      return userInfo;
+    }
+    return null;
+  }
+
+  /**
+   * @description: 生成 token
+   */
+  async generateTokens(userInfo: User): Promise<Pick<User, 'token'>> {
+    const payload: CommonType.TokenPayload = { userName: userInfo.userName, sub: userInfo.id };
+
+    const token = this.jwtService.sign(payload, {
+      expiresIn: '3d', // 设置访问 token 的过期时间为 3 天
+    });
+
+    return { token };
+  }
+
+  /**
+   * @description: 用户注销登录
+   */
+  async logout(session) {
+    const { userInfo } = session;
+    const { id } = userInfo;
+    // 清空数据库中 token
+    await this.prisma.user.update({
+      where: { id },
+      data: { token: null },
+    });
+    // 清除 session
+    session.destroy();
+    // 保存操作日志
+    return responseMessage({}, '注销成功');
+  }
+
+  /**
+   * @description: 用于生成密码的哈希值
+   */
+  async hashPassword(password: string): Promise<string> {
+    const saltOrRounds = 10; // 盐轮数
+    return bcrypt.hash(password, saltOrRounds);
+  }
+
+  /**
+   * @description: 用于验证用户提供的密码是否与数据库中存储的哈希密码匹配
+   */
+  async comparePassword(password: string, hashedPassword: string): Promise<boolean> {
+    return bcrypt.compare(password, hashedPassword);
+  }
+
+  /**
+   * @description: 获取国际化数据
+   */
+  async getLocales() {
+    // 查询全部数据
+    const sqlData = await this.prisma.internalization.findMany({
+      orderBy: [{ createdAt: 'desc' }],
+    });
+    // 将数据转成树形结构
+    const localesTree = convertFlatDataToTree(sqlData);
+    // 转成层级对象
+    const result = convertToLocalization(localesTree);
+    return responseMessage<CommonType.LanguageResult>(result);
+  }
+
+  /**
+   * @description: 掘金文章列表
+   */
+  async juejin(params: juejinParamsDto) {
+    const url = 'https://api.juejin.cn/content_api/v1/article/query_list';
+    const responseData: any = await lastValueFrom(this.httpService.post(url, params).pipe(map((res) => res.data)));
+    return responseMessage({
+      list: responseData.data,
+      total: responseData.count,
+    });
+  }
+
+  /**
+   * @description: 获取动态路由表
+   */
+  async getConstantRoutes() {
+    // 获取菜单列表
+    const result = await this.prisma.menu.findMany({
+      where: {
+        // 过滤出 json 对象只有常量的菜单
+        meta: {
+          path: ['constant'],
+          equals: true,
+        },
+      },
+      select: {
+        name: true,
+        path: true,
+        component: true,
+        meta: true,
+      },
+      orderBy: [
+        { sort: 'asc' }, // 按照sort字段升序
+        { createdAt: 'desc' }, // 如果sort相同,再按照createdAt字段降序
+      ],
+    });
+    return responseMessage<Menu[]>(result);
+  }
+
+  /**
+   * @description: 获取用户路由
+   */
+  async getUserRoutes(session: CommonType.SessionInfo) {
+    // 获取所有与 roleId 相关的 menuId
+    const menuIds = await this.prisma.permission
+      .findMany({
+        where: {
+          roleId: session.userInfo.roleId,
+        },
+        select: {
+          menuId: true,
+        },
+      })
+      .then((results) => results.map((result) => result.menuId));
+    // 获取菜单列表
+    const result = await this.prisma.menu.findMany({
+      where: {
+        type: {
+          not: MenuType.BUTTON,
+        },
+        id: {
+          in: menuIds,
+        },
+        // 过滤出 json 对象不是常量的菜单
+        meta: {
+          path: ['constant'],
+          not: true,
+        },
+      },
+      select: {
+        id: true,
+        parentId: true,
+        name: true,
+        path: true,
+        component: true,
+        meta: true,
+        props: true,
+      },
+      orderBy: [
+        { sort: 'asc' }, // 按照sort字段升序
+        { createdAt: 'desc' }, // 如果sort相同,再按照createdAt字段降序
+      ],
+    });
+    // 转成树形结构
+    const routes = convertFlatDataToTree(result);
+    return responseMessage({
+      home: routes?.[0]?.name || 'home',
+      routes,
+    });
+  }
+
+  /**
+   * @description: 判断路由名称是否存在
+   */
+  async isRouteExist(name: string) {
+    const result = await this.prisma.menu.findUnique({
+      where: {
+        name,
+      },
+    });
+    return responseMessage<boolean>(result ? true : false);
+  }
+
+  /**
+   * @description: 获取角色权限路由
+   */
+  async getRoleRoutes() {
+    // 获取菜单列表
+    const result = await this.prisma.menu.findMany({
+      where: {
+        OR: [
+          {
+            type: {
+              equals: MenuType.BUTTON,
+            },
+          },
+          {
+            AND: [
+              {
+                // 过滤出 json 对象不是常量的菜单
+                meta: {
+                  path: ['constant'],
+                  not: true,
+                },
+              },
+            ],
+          },
+        ],
+      },
+      orderBy: [
+        { sort: 'asc' }, // 按照sort字段升序
+        { createdAt: 'desc' }, // 如果sort相同,再按照createdAt字段降序
+      ],
+    });
+    // 转成树形结构
+    const routes = convertFlatDataToTree(result);
+    return responseMessage(routes);
+  }
+}

+ 80 - 0
server/src/modules/auth/dto/params-auth.dto.ts

@@ -0,0 +1,80 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-08-01 15:35:28
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-20 15:42:13
+ * @Description: 请求参数 DTO
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { IsNotEmpty } from 'class-validator';
+
+/**
+ * @description: 用户登录参数
+ */
+export class LoginParamsDto {
+  @ApiProperty({
+    type: String,
+    description: '用户名',
+    default: 'admin',
+  })
+  @IsNotEmpty({ message: '用户名必填' })
+  userName: string;
+
+  @ApiProperty({
+    type: String,
+    description: '密码',
+    default: 'abc123456',
+  })
+  @IsNotEmpty({ message: '密码必填' })
+  password: string;
+
+  @ApiProperty({
+    type: String,
+    description: '验证码',
+    default: '16',
+  })
+  @IsNotEmpty({ message: '验证码必填' })
+  captchaCode: string;
+}
+
+/**
+ * @description: 掘金文章列表
+ */
+export class juejinParamsDto {
+  @ApiProperty({
+    type: String,
+    description: '用户id',
+    default: '1917147257534279',
+  })
+  @IsNotEmpty({ message: '用户id必填' })
+  user_id: string;
+
+  @ApiProperty({
+    type: Number,
+    description: '文章类型',
+    default: 2,
+  })
+  @IsNotEmpty({ message: '文章类型必填' })
+  sort_type: number;
+
+  @ApiProperty({
+    type: String,
+    description: '文章偏移量',
+    default: '5',
+  })
+  @IsNotEmpty({ message: '文章偏移量必填' })
+  cursor: string;
+}
+
+/**
+ * @description: 判断路由是否存在
+ */
+export class RouteExistParamsDto {
+  @ApiProperty({
+    type: String,
+    description: '路由名称',
+    default: 'home',
+  })
+  @IsNotEmpty({ message: '路由名称必填' })
+  name: string;
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 67 - 0
server/src/modules/auth/dto/response-auth.dto.ts


+ 48 - 0
server/src/modules/auth/jwt.strategy.ts

@@ -0,0 +1,48 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-08-01 16:32:15
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-05 14:06:24
+ * @Description: JWT 鉴权模块
+ */
+import { Injectable, UnauthorizedException } from '@nestjs/common';
+import { PassportStrategy } from '@nestjs/passport';
+import { Request } from 'express';
+import { ExtractJwt, Strategy } from 'passport-jwt';
+
+import { PrismaService } from '@/modules/prisma/prisma.service';
+
+@Injectable()
+export class JwtStrategy extends PassportStrategy(Strategy) {
+  constructor(private prisma: PrismaService) {
+    super({
+      // 提供从请求中提取 JWT 的方法。我们将使用在 API 请求的授权头中提供token的标准方法
+      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
+      // 为了明确起见,我们选择默认的 false 设置,
+      // 它将确保 JWT 没有过期的责任委托给 Passport 模块。
+      // 这意味着,如果我们的路由提供了一个过期的 JWT ,请求将被拒绝,并发送 401 未经授权的响应。Passport 会自动为我们办理
+      ignoreExpiration: false,
+      // 使用权宜的选项来提供对称的秘密来签署令牌
+      secretOrKey: process.env.JWT_SECRET,
+      passReqToCallback: true,
+    });
+  }
+
+  async validate(req: Request, payload: CommonType.TokenPayload) {
+    // 获取当前 token
+    const token = ExtractJwt.fromAuthHeaderAsBearerToken()(req);
+    // 缺少令牌
+    if (!token) {
+      throw new UnauthorizedException('未登录');
+    }
+    const user = await this.prisma.user.findUnique({
+      where: {
+        id: payload.sub,
+      },
+    });
+    if (!user) {
+      throw new UnauthorizedException('token令牌非法,请重新登录');
+    }
+    return payload;
+  }
+}

+ 77 - 0
server/src/modules/code-type/code-type.controller.ts

@@ -0,0 +1,77 @@
+/*
+ * @Description: CodeTypeController - 激活码类型管理
+ */
+import { Body, Controller, Delete, Get, Param, Post, Put, Query, UseGuards, UseInterceptors } from '@nestjs/common';
+import { AuthGuard } from '@nestjs/passport';
+import { ApiBearerAuth, ApiHeader, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger';
+
+import { LoggerInterceptor } from '@/interceptor/logger.interceptor';
+
+import { CodeTypeService } from './code-type.service';
+import { CodeTypeParamsDto } from './dto/params-code-type.dto';
+import { ResponseSaveCodeTypeDto } from './dto/response-code-type.dto';
+import { SaveCodeTypeDto } from './dto/save-code-type.dto';
+
+@ApiTags('激活码类型管理')
+@ApiHeader({
+  name: 'Authorization',
+  required: true,
+  description: 'token令牌',
+})
+@ApiBearerAuth()
+@Controller('code-type')
+@UseInterceptors(LoggerInterceptor)
+@UseGuards(AuthGuard('jwt'))
+export class CodeTypeController {
+  constructor(private readonly codeTypeService: CodeTypeService) {}
+
+  /**
+   * @description: 获取激活码类型列表
+   */
+  @Get()
+  @ApiOkResponse({ type: ResponseSaveCodeTypeDto })
+  @ApiOperation({ summary: '获取激活码类型列表' })
+  findAll(@Query() params: CodeTypeParamsDto) {
+    return this.codeTypeService.findAll(params);
+  }
+
+  /**
+   * @description: 获取激活码类型详情
+   */
+  @Get(':id')
+  @ApiOkResponse({ type: ResponseSaveCodeTypeDto })
+  @ApiOperation({ summary: '获取激活码类型详情' })
+  findOne(@Param('id') id: string) {
+    return this.codeTypeService.findOne(id);
+  }
+
+  /**
+   * @description: 创建激活码类型
+   */
+  @Post()
+  @ApiOkResponse({ type: ResponseSaveCodeTypeDto })
+  @ApiOperation({ summary: '创建激活码类型' })
+  create(@Body() body: SaveCodeTypeDto) {
+    return this.codeTypeService.create(body);
+  }
+
+  /**
+   * @description: 更新激活码类型
+   */
+  @Put(':id')
+  @ApiOkResponse({ type: ResponseSaveCodeTypeDto })
+  @ApiOperation({ summary: '更新激活码类型' })
+  update(@Param('id') id: string, @Body() body: SaveCodeTypeDto) {
+    return this.codeTypeService.update(id, body);
+  }
+
+  /**
+   * @description: 删除激活码类型
+   */
+  @Delete(':id')
+  @ApiOkResponse({ type: ResponseSaveCodeTypeDto })
+  @ApiOperation({ summary: '删除激活码类型' })
+  remove(@Param('id') id: string) {
+    return this.codeTypeService.remove(id);
+  }
+}

+ 15 - 0
server/src/modules/code-type/code-type.module.ts

@@ -0,0 +1,15 @@
+import { Module } from '@nestjs/common';
+
+import { PrismaModule } from '@/modules/prisma/prisma.module';
+import { OperationLogModule } from '@/modules/system-manage/operation-log/operation-log.module';
+
+import { CodeTypeController } from './code-type.controller';
+import { CodeTypeService } from './code-type.service';
+
+@Module({
+  imports: [PrismaModule, OperationLogModule],
+  controllers: [CodeTypeController],
+  providers: [CodeTypeService],
+  exports: [CodeTypeService],
+})
+export class CodeTypeModule {}

+ 136 - 0
server/src/modules/code-type/code-type.service.ts

@@ -0,0 +1,136 @@
+/*
+ * @Description: CodeTypeService - 激活码类型管理
+ */
+import { Injectable } from '@nestjs/common';
+import type { ActivationCodeType } from '@prisma/client';
+
+import { RESPONSE_MSG } from '@/enums';
+import { PrismaService } from '@/modules/prisma/prisma.service';
+import { responseMessage } from '@/utils';
+
+import { CodeTypeParamsDto } from './dto/params-code-type.dto';
+import { SaveCodeTypeDto } from './dto/save-code-type.dto';
+
+@Injectable()
+export class CodeTypeService {
+  constructor(private prisma: PrismaService) {}
+
+  /**
+   * @description: 查询激活码类型列表
+   */
+  async findAll(params: CodeTypeParamsDto) {
+    const { name, current = 1, size = 10 } = params;
+
+    const where = {
+      ...(name && { name: { contains: name } }),
+    };
+
+    const [records, total] = await Promise.all([
+      this.prisma.activationCodeType.findMany({
+        where,
+        skip: (+current - 1) * +size,
+        take: +size,
+        orderBy: {
+          createdAt: 'desc',
+        },
+      }),
+      this.prisma.activationCodeType.count({ where }),
+    ]);
+
+    return responseMessage<{
+      records: ActivationCodeType[];
+      total: number;
+      current: number;
+      size: number;
+    }>({
+      records,
+      total,
+      current,
+      size,
+    });
+  }
+
+  /**
+   * @description: 查询激活码类型详情
+   */
+  async findOne(id: string) {
+    const result = await this.prisma.activationCodeType.findUnique({
+      where: { id },
+    });
+
+    if (!result) {
+      return responseMessage(null, '激活码类型不存在', -1);
+    }
+
+    return responseMessage<ActivationCodeType>(result);
+  }
+
+  /**
+   * @description: 创建激活码类型
+   */
+  async create(body: SaveCodeTypeDto) {
+    try {
+      const result = await this.prisma.activationCodeType.create({
+        data: body,
+      });
+
+      return responseMessage<ActivationCodeType>(result);
+    } catch (error) {
+      // 判断是否违反唯一性约束
+      if (error.code === 'P2002') {
+        return responseMessage(null, '激活码类型名称已存在!', -1);
+      }
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 更新激活码类型
+   */
+  async update(id: string, body: SaveCodeTypeDto) {
+    try {
+      const existingCodeType = await this.prisma.activationCodeType.findUnique({
+        where: { id },
+      });
+
+      if (!existingCodeType) {
+        return responseMessage(null, '激活码类型不存在', -1);
+      }
+
+      const result = await this.prisma.activationCodeType.update({
+        where: { id },
+        data: body,
+      });
+
+      return responseMessage<ActivationCodeType>(result);
+    } catch (error) {
+      if (error.code === 'P2002') {
+        return responseMessage(null, '激活码类型名称已存在!', -1);
+      }
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+
+  /**
+   * @description: 删除激活码类型
+   */
+  async remove(id: string) {
+    try {
+      const existingCodeType = await this.prisma.activationCodeType.findUnique({
+        where: { id },
+      });
+
+      if (!existingCodeType) {
+        return responseMessage(null, '激活码类型不存在', -1);
+      }
+
+      await this.prisma.activationCodeType.delete({
+        where: { id },
+      });
+
+      return responseMessage(null, '删除成功');
+    } catch (error) {
+      return responseMessage(error, RESPONSE_MSG.ERROR, -1);
+    }
+  }
+}

+ 41 - 0
server/src/modules/code-type/dto/params-code-type.dto.ts

@@ -0,0 +1,41 @@
+/*
+ * @Description: 激活码类型查询参数 DTO
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { Transform } from 'class-transformer';
+import { IsInt, IsOptional, IsString, Min } from 'class-validator';
+
+export class CodeTypeParamsDto {
+  @ApiProperty({
+    type: String,
+    description: '类型名称(模糊搜索)',
+    required: false,
+  })
+  @IsOptional()
+  @IsString()
+  name?: string;
+
+  @ApiProperty({
+    type: Number,
+    description: '当前页码',
+    default: 1,
+    required: false,
+  })
+  @IsOptional()
+  @Transform(({ value }) => parseInt(value, 10))
+  @IsInt({ message: 'current 参数只能是 number 类型' })
+  @Min(1, { message: 'current 参数不能小于 1' })
+  current?: number = 1;
+
+  @ApiProperty({
+    type: Number,
+    description: '每页条数',
+    default: 10,
+    required: false,
+  })
+  @IsOptional()
+  @Transform(({ value }) => parseInt(value, 10))
+  @IsInt({ message: 'size 参数只能是 number 类型' })
+  @Min(1, { message: 'size 参数不能小于 1' })
+  size?: number = 10;
+}

+ 29 - 0
server/src/modules/code-type/dto/response-code-type.dto.ts

@@ -0,0 +1,29 @@
+/*
+ * @Description: 激活码类型响应数据 Dto
+ */
+import { ApiProperty } from '@nestjs/swagger';
+
+export class ResponseCodeTypeDto {
+  @ApiProperty({ type: String, description: '主键' })
+  id: string;
+
+  @ApiProperty({ type: String, description: '类型名称' })
+  name: string;
+
+  @ApiProperty({ type: String, description: '创建时间' })
+  createdAt: string;
+
+  @ApiProperty({ type: String, description: '更新时间' })
+  updatedAt: string;
+}
+
+export class ResponseSaveCodeTypeDto {
+  @ApiProperty({ type: Number, description: '业务状态码' })
+  code: number;
+
+  @ApiProperty({ type: String, description: '业务信息' })
+  msg: string;
+
+  @ApiProperty({ type: ResponseCodeTypeDto, description: '响应数据' })
+  data: ResponseCodeTypeDto;
+}

+ 16 - 0
server/src/modules/code-type/dto/save-code-type.dto.ts

@@ -0,0 +1,16 @@
+/*
+ * @Description: 保存激活码类型数据 Dto
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { IsNotEmpty, IsString } from 'class-validator';
+
+export class SaveCodeTypeDto {
+  @ApiProperty({
+    type: String,
+    description: '激活码类型名称',
+    default: '30天KEY',
+  })
+  @IsNotEmpty({ message: '类型名称必填' })
+  @IsString({ message: '类型名称必须是字符串' })
+  name: string;
+}

+ 40 - 0
server/src/modules/file-upload/dto/index.ts

@@ -0,0 +1,40 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-29 14:43:48
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-07-31 15:21:52
+ * @Description: 上传文件 Dto
+ */
+import { ApiProperty } from '@nestjs/swagger';
+
+import { ResponseDto } from '@/dto/response.dto';
+
+export class FileUploadDto {
+  @ApiProperty({
+    type: String,
+    description: '文件流',
+    format: 'binary',
+  })
+  file: any;
+}
+
+/**
+ * @description: 单个文件上传
+ */
+export class SingleFileResponseDto extends ResponseDto {
+  @ApiProperty({
+    type: String,
+    description: '单个文件上传',
+    default: {
+      fieldname: 'file',
+      originalname: '1.jpg',
+      encoding: '7bit',
+      mimetype: 'image/jpeg',
+      destination: './upload/image/2024-07',
+      filename: '07614707-436a-49b3-b8e3-1fcbd1398600.jpeg',
+      path: 'http://localhost:3000/static/image/2024-07/07614707-436a-49b3-b8e3-1fcbd1398600.jpeg',
+      size: 40232,
+    },
+  })
+  data: Record<string, any>;
+}

+ 47 - 0
server/src/modules/file-upload/file-upload.controller.ts

@@ -0,0 +1,47 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-29 14:24:19
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-02 10:01:55
+ * @Description: FileUploadController
+ */
+import { Controller, Post, Req, UploadedFile, UseGuards, UseInterceptors } from '@nestjs/common';
+import { AuthGuard } from '@nestjs/passport';
+import { FileInterceptor } from '@nestjs/platform-express';
+import { ApiBearerAuth, ApiBody, ApiConsumes, ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger';
+import { Request } from 'express';
+
+import { responseMessage } from '@/utils';
+
+import { FileUploadDto, SingleFileResponseDto } from './dto';
+
+@ApiTags('文件上传')
+@ApiHeader({
+  name: 'Authorization',
+  required: true,
+  description: 'token令牌',
+})
+@ApiBearerAuth()
+@Controller('upload')
+export class FileUploadController {
+  /**
+   * @description: 上传单个文件
+   */
+  @UseGuards(AuthGuard('jwt'))
+  @UseInterceptors(FileInterceptor('file'))
+  @Post('single-file')
+  @ApiConsumes('multipart/form-data')
+  @ApiOkResponse({ type: SingleFileResponseDto })
+  @ApiBody({
+    description: '单个文件上传',
+    type: FileUploadDto,
+  })
+  uploadFile(@UploadedFile() file: Express.Multer.File, @Req() req: Request): CommonType.Response<Express.Multer.File> {
+    // 获取客户端域名端口
+    const hostname = req.headers['x-forwarded-host'] || req.hostname;
+    const port = req.headers['x-forwarded-port'] || req.socket.localPort;
+    const protocol = req.headers['x-forwarded-proto'] || req.protocol;
+    file.path = `${protocol}://${hostname}:${port}/static${file.path.replace(/\\/g, '/').replace(/upload/g, '')}`;
+    return responseMessage(file);
+  }
+}

+ 63 - 0
server/src/modules/file-upload/file-upload.module.ts

@@ -0,0 +1,63 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-29 14:34:29
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-07-29 15:51:48
+ * @Description: FileUploadModule
+ */
+import { Module } from '@nestjs/common';
+import { MulterModule } from '@nestjs/platform-express';
+import dayjs from 'dayjs';
+import { diskStorage } from 'multer';
+import { v4 as uuidv4 } from 'uuid';
+
+import { checkDirAndCreate } from '@/utils';
+
+import { FileUploadController } from './file-upload.controller';
+import { FileUploadService } from './file-upload.service';
+
+@Module({
+  imports: [
+    MulterModule.registerAsync({
+      useFactory: async () => ({
+        limits: {
+          fileSize: 1024 * 1024 * 5, // 限制文件大小为 5MB
+        },
+        storage: diskStorage({
+          // 配置文件上传后的文件夹路径
+          destination: (_, file, cb) => {
+            // 定义文件上传格式
+            const allowedImageTypes = ['gif', 'png', 'jpg', 'jpeg', 'bmp', 'webp', 'svg', 'tiff']; // 图片
+            const allowedOfficeTypes = ['xls', 'xlsx', 'doc', 'docx', 'ppt', 'pptx', 'pdf', 'txt', 'md', 'csv']; // office
+            const allowedVideoTypes = ['mp4', 'avi', 'wmv']; // 视频
+            const allowedAudioTypes = ['mp3', 'wav', 'ogg']; // 音频
+            // 根据上传的文件类型将图片视频音频和其他类型文件分别存到对应英文文件夹
+            const fileExtension = file.originalname.split('.').pop().toLowerCase();
+            let temp = 'other';
+            if (allowedImageTypes.includes(fileExtension)) {
+              temp = 'image';
+            } else if (allowedOfficeTypes.includes(fileExtension)) {
+              temp = 'office';
+            } else if (allowedVideoTypes.includes(fileExtension)) {
+              temp = 'video';
+            } else if (allowedAudioTypes.includes(fileExtension)) {
+              temp = 'audio';
+            }
+            // 文件以年月命名文件夹
+            const filePath = `upload/${temp}/${dayjs().format('YYYY-MM')}`;
+            checkDirAndCreate(filePath); // 判断文件夹是否存在,不存在则自动生成
+            return cb(null, `./${filePath}`);
+          },
+          filename: (_, file, cb) => {
+            // 使用随机 uuid 生成文件名
+            const filename = `${uuidv4()}.${file.mimetype.split('/')[1]}`;
+            return cb(null, filename);
+          },
+        }),
+      }),
+    }),
+  ],
+  controllers: [FileUploadController],
+  providers: [FileUploadService],
+})
+export class FileUploadModule { }

+ 11 - 0
server/src/modules/file-upload/file-upload.service.ts

@@ -0,0 +1,11 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-29 14:20:28
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-07-29 14:20:41
+ * @Description: FileUploadService
+ */
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class FileUploadService { }

+ 16 - 0
server/src/modules/prisma/prisma.module.ts

@@ -0,0 +1,16 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-10 13:47:29
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-07-10 13:47:40
+ * @Description: PrismaModule
+ */
+import { Module } from '@nestjs/common';
+
+import { PrismaService } from './prisma.service';
+
+@Module({
+  providers: [PrismaService],
+  exports: [PrismaService],
+})
+export class PrismaModule { }

+ 25 - 0
server/src/modules/prisma/prisma.service.ts

@@ -0,0 +1,25 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-07-10 13:46:51
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-30 09:23:26
+ * @Description: PrismaService
+ */
+import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
+import { PrismaClient } from '@prisma/client';
+
+@Injectable()
+export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
+  constructor() {
+    super({
+      log: ['query', 'info', 'warn', 'error'], // 这里设置日志级别
+    });
+  }
+  async onModuleInit() {
+    await this.$connect(); // 在模块初始化时连接到数据库
+  }
+
+  async onModuleDestroy() {
+    await this.$disconnect(); // 在应用程序关闭时断开与数据库的连
+  }
+}

+ 47 - 0
server/src/modules/system-manage/internalization/dto/params-internalization.dto.ts

@@ -0,0 +1,47 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-08-14 17:52:40
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-09-09 18:08:26
+ * @Description: 请求参数 DTO
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { IsNumberString, IsOptional } from 'class-validator';
+
+export class InternalizationParamsDto {
+  @ApiProperty({
+    type: String,
+    description: '多语言字段',
+    required: false,
+    default: 'menu',
+  })
+  name?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '中文',
+    required: false,
+    default: '首页',
+  })
+  zhCN?: string;
+
+  @ApiProperty({
+    type: Number,
+    description: '开始日期',
+    default: 1721145600000,
+    required: false,
+  })
+  @IsOptional()
+  @IsNumberString({}, { message: '开始日期必须是时间戳格式' })
+  startTime?: number;
+
+  @ApiProperty({
+    type: Number,
+    description: '结束日期',
+    default: 1721318399999,
+    required: false,
+  })
+  @IsOptional()
+  @IsNumberString({}, { message: '结束日期必须是时间戳格式' })
+  endTime?: number;
+}

+ 59 - 0
server/src/modules/system-manage/internalization/dto/response-internalization.dto.ts

@@ -0,0 +1,59 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-08-15 10:02:55
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-22 15:26:31
+ * @Description: 响应体
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import type { Internalization } from '@prisma/client';
+
+import { ResponseDto } from '@/dto/response.dto';
+
+/**
+ * @description: 国际化列表响应体结构 Dto
+ */
+export class ResponseInternalizationDto extends ResponseDto {
+  @ApiProperty({
+    type: Array,
+    description: '响应体',
+    default: {
+      records: [
+        {
+          id: '9ec5117e-370f-4785-8ea4-42fc72399be2',
+          name: 'updateTitle',
+          parentId: '54d1a5bd-0275-4a27-a613-63f679a50d4d',
+          zhCN: '系统版本更新通知',
+          enUS: 'System version update notification',
+          jaJP: 'システム更新のお知らせです',
+          zhTW: '系統版本更新通知',
+          createdAt: '2024-08-15T02:59:31.025Z',
+          updatedAt: '2024-08-15T02:59:31.025Z',
+        },
+      ],
+    },
+  })
+  data: Internalization[];
+}
+
+/**
+ * @description: 创建/更新/删除国际化数据 Dto
+ */
+export class ResponseSaveInternalizationDto extends ResponseDto {
+  @ApiProperty({
+    type: Object,
+    description: '响应体',
+    default: {
+      id: '9ec5117e-370f-4785-8ea4-42fc72399be2',
+      name: 'updateTitle',
+      parentId: '54d1a5bd-0275-4a27-a613-63f679a50d4d',
+      zhCN: '系统版本更新通知',
+      enUS: 'System version update notification',
+      jaJP: 'システム更新のお知らせです',
+      zhTW: '系統版本更新通知',
+      createdAt: '2024-08-15T02:59:31.025Z',
+      updatedAt: '2024-08-15T02:59:31.025Z',
+    },
+  })
+  data: Internalization;
+}

+ 61 - 0
server/src/modules/system-manage/internalization/dto/save-internalization.dto.ts

@@ -0,0 +1,61 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-08-15 10:44:35
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-15 11:01:13
+ * @Description: 保存国际化数据
+ */
+import { ApiProperty } from '@nestjs/swagger';
+import { IsNotEmpty, IsOptional, IsUUID } from 'class-validator';
+
+export class SaveInternalizationDto {
+  @ApiProperty({
+    type: String,
+    description: '国际化字段',
+    default: 'login',
+  })
+  @IsNotEmpty({ message: '国际化字段必填' })
+  name: string;
+
+  @ApiProperty({
+    type: String,
+    description: '父级id',
+    default: '0c01ef7d-2f6f-440a-b642-62564d41f473',
+    required: false,
+  })
+  @IsOptional()
+  @IsUUID('all', { message: 'parentId 参数不正确' })
+  parentId?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '中文',
+    default: '统版本更新通知',
+    required: false,
+  })
+  zhCN?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '英文',
+    default: 'System version update notification',
+    required: false,
+  })
+  enUS?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '日文',
+    default: 'システム更新のお知らせです',
+    required: false,
+  })
+  jaJP?: string;
+
+  @ApiProperty({
+    type: String,
+    description: '繁体中文',
+    default: '系統版本更新通知',
+    required: false,
+  })
+  zhTW?: string;
+}

+ 83 - 0
server/src/modules/system-manage/internalization/internalization.controller.ts

@@ -0,0 +1,83 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-08-15 09:54:56
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-26 09:01:57
+ * @Description: InternalizationController
+ */
+import {
+  Body,
+  Controller,
+  Delete,
+  Get,
+  Param,
+  ParseUUIDPipe,
+  Post,
+  Put,
+  Query,
+  UseGuards,
+  UseInterceptors,
+} from '@nestjs/common';
+import { AuthGuard } from '@nestjs/passport';
+import { ApiBearerAuth, ApiHeader, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; // swagger 接口文档
+
+import { LoggerInterceptor } from '@/interceptor/logger.interceptor';
+
+import { InternalizationParamsDto } from './dto/params-internalization.dto';
+import { ResponseInternalizationDto, ResponseSaveInternalizationDto } from './dto/response-internalization.dto';
+import { SaveInternalizationDto } from './dto/save-internalization.dto';
+import { InternalizationService } from './internalization.service';
+
+@ApiTags('系统管理-国际化')
+@ApiHeader({
+  name: 'Authorization',
+  required: true,
+  description: 'token令牌',
+})
+@ApiBearerAuth()
+@Controller('system/internalization')
+@UseInterceptors(LoggerInterceptor)
+@UseGuards(AuthGuard('jwt'))
+export class InternalizationController {
+  constructor(private readonly internalizationService: InternalizationService) { }
+
+  /**
+   * @description: 查询国际化列表
+   */
+  @Get()
+  @ApiOkResponse({ type: ResponseInternalizationDto })
+  @ApiOperation({ summary: '获取国际化列表' })
+  findAll(@Query() params: InternalizationParamsDto) {
+    return this.internalizationService.findAll(params);
+  }
+
+  /**
+   * @description: 创建国际化
+   */
+  @Post()
+  @ApiOkResponse({ type: ResponseSaveInternalizationDto })
+  @ApiOperation({ summary: '创建国际化' })
+  create(@Body() body: SaveInternalizationDto) {
+    return this.internalizationService.create(body);
+  }
+
+  /**
+   * @description: 更新国际化
+   */
+  @Put(':id')
+  @ApiOkResponse({ type: ResponseSaveInternalizationDto })
+  @ApiOperation({ summary: '更新国际化' })
+  update(@Param('id', new ParseUUIDPipe()) id: string, @Body() body: SaveInternalizationDto) {
+    return this.internalizationService.update(id, body);
+  }
+
+  /**
+   * @description: 删除国际化
+   */
+  @Delete(':id')
+  @ApiOkResponse({ type: ResponseSaveInternalizationDto })
+  @ApiOperation({ summary: '删除国际化' })
+  remove(@Param('id', new ParseUUIDPipe()) id: string) {
+    return this.internalizationService.remove(id);
+  }
+}

+ 22 - 0
server/src/modules/system-manage/internalization/internalization.module.ts

@@ -0,0 +1,22 @@
+/*
+ * @Author: 白雾茫茫丶<baiwumm.com>
+ * @Date: 2024-08-15 10:54:25
+ * @LastEditors: 白雾茫茫丶<baiwumm.com>
+ * @LastEditTime: 2024-08-15 10:55:12
+ * @Description: InternalizationModule
+ */
+import { Module } from '@nestjs/common';
+
+import { PrismaModule } from '@/modules/prisma/prisma.module';
+import { OperationLogModule } from '@/modules/system-manage/operation-log/operation-log.module';
+
+import { InternalizationController } from './internalization.controller';
+import { InternalizationService } from './internalization.service';
+
+@Module({
+  imports: [PrismaModule, OperationLogModule],
+  controllers: [InternalizationController],
+  providers: [InternalizationService],
+  exports: [InternalizationService],
+})
+export class InternalizationModule { }

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است