@ -0,0 +1,4 @@ |
|||||
|
.github |
||||
|
.vscode/ |
||||
|
dist/ |
||||
|
node_modules/ |
||||
@ -0,0 +1 @@ |
|||||
|
VITE_GLOB_APP_TITLE = Vite React TS Template |
||||
@ -0,0 +1,12 @@ |
|||||
|
VITE_APP_BASE_API= |
||||
|
VITE_APP_HOMEPAGE=/dashboard/workbench |
||||
|
VITE_APP_BASE_PATH=/ |
||||
|
# VITE_GLOB_CLIENT_ID=react-admin-client |
||||
|
# VITE_GLOB_CLIENT_SECRET='' |
||||
|
# VITE_GLOB_SCOPE="openid email address phone profile offline_access miwen-abp-application" |
||||
|
# VITE_PROXY_API=http://192.168.31.246:30001 |
||||
|
|
||||
|
VITE_GLOB_CLIENT_ID=vue-admin-client |
||||
|
VITE_GLOB_CLIENT_SECRET=1q2w3e* |
||||
|
VITE_GLOB_SCOPE="openid email address phone profile offline_access lingyun-abp-application" |
||||
|
VITE_PROXY_API=http://124.223.5.95:30001 |
||||
@ -0,0 +1,3 @@ |
|||||
|
VITE_APP_BASE_API=/api |
||||
|
VITE_APP_HOMEPAGE=/dashboard/workbench |
||||
|
VITE_APP_BASE_PATH=/ |
||||
@ -0,0 +1,28 @@ |
|||||
|
# Logs |
||||
|
logs |
||||
|
*.log |
||||
|
npm-debug.log* |
||||
|
yarn-debug.log* |
||||
|
yarn-error.log* |
||||
|
pnpm-debug.log* |
||||
|
lerna-debug.log* |
||||
|
|
||||
|
node_modules |
||||
|
dist |
||||
|
dist-ssr |
||||
|
*.local |
||||
|
|
||||
|
# Editor directories and files |
||||
|
.idea |
||||
|
.DS_Store |
||||
|
*.suo |
||||
|
*.ntvs* |
||||
|
*.njsproj |
||||
|
*.sln |
||||
|
*.sw? |
||||
|
|
||||
|
# vite 打包分析产物 |
||||
|
stats.html |
||||
|
|
||||
|
# 取消上层忽略 |
||||
|
!.vscode/ |
||||
@ -0,0 +1,7 @@ |
|||||
|
{ |
||||
|
"recommendations": [ |
||||
|
"biomejs.biome", |
||||
|
"bradlc.vscode-tailwindcss", |
||||
|
"lokalise.i18n-ally" |
||||
|
] |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
{ |
||||
|
"typescript.tsdk": "./node_modules/typescript/lib", |
||||
|
"editor.tabSize": 2, |
||||
|
"editor.formatOnSave": true, |
||||
|
"editor.codeActionsOnSave": { |
||||
|
"quickfix.biome": "explicit", |
||||
|
"source.organizeImports.biome": "explicit" |
||||
|
}, |
||||
|
"editor.quickSuggestions": { |
||||
|
"strings": "on" |
||||
|
}, |
||||
|
"tailwindCSS.experimental.classRegex": [ |
||||
|
["cn\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"] |
||||
|
], |
||||
|
"npm.packageManager": "pnpm", |
||||
|
"i18n-ally.localesPaths": ["src/locales/lang"], |
||||
|
"i18n-ally.enabledParsers": ["json"], |
||||
|
"i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}", |
||||
|
"i18n-ally.keystyle": "flat", |
||||
|
"i18n-ally.sortKeys": true, |
||||
|
"i18n-ally.sourceLanguage": "en_US", |
||||
|
"i18n-ally.displayLanguage": "zh_CN", |
||||
|
"[javascript]": { |
||||
|
"editor.defaultFormatter": "biomejs.biome" |
||||
|
}, |
||||
|
"[typescript]": { |
||||
|
"editor.defaultFormatter": "biomejs.biome" |
||||
|
}, |
||||
|
"[typescriptreact]": { |
||||
|
"editor.defaultFormatter": "biomejs.biome" |
||||
|
}, |
||||
|
"[json]": { |
||||
|
"editor.defaultFormatter": "biomejs.biome" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
# Stage 1: build stage |
||||
|
FROM node:22-alpine as build-stage |
||||
|
# make the 'app' folder the current working directory |
||||
|
WORKDIR /app |
||||
|
# config node options |
||||
|
ENV NODE_OPTIONS=--max_old_space_size=8192 |
||||
|
# config pnpm, install dependencies |
||||
|
COPY package.json pnpm-lock.yaml* ./ |
||||
|
RUN npm install pnpm@9.x -g && \ |
||||
|
pnpm install --frozen-lockfile |
||||
|
# copy project files and folders to the current working directory (i.e. 'app' folder) |
||||
|
COPY . ./ |
||||
|
# build the project |
||||
|
RUN pnpm build |
||||
|
RUN echo "build successful 🎉 🎉 🎉" |
||||
|
|
||||
|
|
||||
|
# Stage 2: production stage |
||||
|
FROM nginx:latest as production-stage |
||||
|
COPY --from=build-stage /app/dist /usr/share/nginx/html |
||||
|
EXPOSE 80 |
||||
|
CMD ["nginx", "-g", "daemon off;"] |
||||
|
RUN echo "deploy to nginx successful 🎉 🎉 🎉" |
||||
|
|
||||
@ -0,0 +1,21 @@ |
|||||
|
MIT License |
||||
|
|
||||
|
Copyright (c) 2023 d3george |
||||
|
|
||||
|
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. |
||||
@ -0,0 +1,132 @@ |
|||||
|
<div align="center"> |
||||
|
<br> |
||||
|
<br> |
||||
|
<img src="./src/assets/images/logo.png" height="140" /> |
||||
|
<h3> Slash Admin </h3> |
||||
|
<p> |
||||
|
<p style="font-size: 14px"> |
||||
|
Slash Admin is a modern admin dashboard template built with React 18, Vite, Ant Design, and TypeScript. It is designed to help developers quickly create powerful admin management systems. |
||||
|
</p> |
||||
|
<br /> |
||||
|
<br /> |
||||
|
<a href="https://admin.slashspaces.com/">Preview</a> |
||||
|
· |
||||
|
<a href="https://discord.gg/fXemAXVNDa">Discord</a> |
||||
|
· |
||||
|
<a href="https://docs-admin.slashspaces.com/">Document</a> |
||||
|
<br /> |
||||
|
<br /> |
||||
|
<a href="https://trendshift.io/repositories/6387" target="_blank"><img src="https://trendshift.io/api/badge/repositories/6387" alt="d3george%2Fslash-admin | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a> |
||||
|
</div> |
||||
|
|
||||
|
**English** | [中文](./README.zh-CN.md) |
||||
|
|
||||
|
## Sponsor |
||||
|
<div style="display: flex; gap: 50px"> |
||||
|
<img style="width:300px" src="https://d3george.github.io/github-static/pay/weixin.jpg" > |
||||
|
<img style="width:280px" src="https://d3george.github.io/github-static/pay/buymeacoffee.png" /> |
||||
|
</div> |
||||
|
|
||||
|
## Preview |
||||
|
+ https://admin.slashspaces.com/ |
||||
|
|
||||
|
|| |
||||
|
| ----------------------------------------------------------------- | ------------------------------------------------------------------- | |
||||
|
|| |
||||
|
|
||||
|
## Features |
||||
|
|
||||
|
- Built using React 18 hooks. |
||||
|
- Powered by Vite for rapid development and hot module replacement. |
||||
|
- Integrates Ant Design, providing a rich set of UI components and design patterns. |
||||
|
- Written in TypeScript, offering type safety and an improved development experience. |
||||
|
- Responsive design, adapting to various screen sizes and devices. |
||||
|
- Flexible routing configuration, supporting nested routes. |
||||
|
- Integrated access control based on user roles. |
||||
|
- Supports internationalization for easy language switching. |
||||
|
- Includes common admin features like user management, role management, and permission management. |
||||
|
- Customizable themes and styles to meet your branding needs. |
||||
|
- Mocking solution based on MSW and Faker.js. |
||||
|
- State management using Zustand. |
||||
|
- Data fetching using React-Query. |
||||
|
|
||||
|
## Quick Start |
||||
|
|
||||
|
### Get the Project Code |
||||
|
|
||||
|
```bash |
||||
|
git clone https://github.com/d3george/slash-admin.git |
||||
|
``` |
||||
|
|
||||
|
### Install Dependencies |
||||
|
|
||||
|
In the project's root directory, run the following command to install project dependencies: |
||||
|
|
||||
|
```bash |
||||
|
pnpm install |
||||
|
``` |
||||
|
|
||||
|
### Start the Development Server |
||||
|
|
||||
|
Run the following command to start the development server: |
||||
|
|
||||
|
```bash |
||||
|
pnpm dev |
||||
|
``` |
||||
|
|
||||
|
Visit [http://localhost:3001](http://localhost:3001) to view your application. |
||||
|
|
||||
|
### Build for Production |
||||
|
|
||||
|
Run the following command to build the production version: |
||||
|
|
||||
|
```bash |
||||
|
pnpm build |
||||
|
``` |
||||
|
|
||||
|
## Docker deployment |
||||
|
|
||||
|
|
||||
|
### Build image and Run container |
||||
|
#### build image |
||||
|
Enter the project root directory in the terminal and execute the following command to build the Docker image: |
||||
|
``` |
||||
|
docker build -t your-image-name . |
||||
|
``` |
||||
|
Make sure to replace `your-image-name` with your own image name |
||||
|
|
||||
|
#### run container |
||||
|
Run your application in the Docker container using the following command: |
||||
|
``` |
||||
|
docker run -p 3001:80 your-image-name |
||||
|
``` |
||||
|
This will run your application on port `80`(exposed in `Dockerfile`) of the container and map it to port `3001` on your host. |
||||
|
|
||||
|
Now you can access http://localhost:3001 to view the deployed applications. |
||||
|
|
||||
|
### use docker-compose.yaml |
||||
|
Enter the project root directory in the terminal and execute the following command to start Docker Compose: |
||||
|
``` |
||||
|
docker-compose up -d |
||||
|
``` |
||||
|
Docker Compose will build an image based on the configuration defined by 'docker-compose. yaml' and run the container in the background. |
||||
|
|
||||
|
After the container runs successfully, it can also be accessed through http://localhost:3001 To view the deployed applications. |
||||
|
|
||||
|
|
||||
|
## Git Contribution submission specification |
||||
|
|
||||
|
reference[.commitlint.config.js](./commitlint.config.js) |
||||
|
|
||||
|
- `feat` new features |
||||
|
- `fix` fix the |
||||
|
- `docs` documentation or comments |
||||
|
- `style` code format (changes that do not affect code execution) |
||||
|
- `refactor` refactor |
||||
|
- `perf` performance optimization |
||||
|
- `revert` revert commit |
||||
|
- `test` test related |
||||
|
- `chore` changes in the construction process or auxiliary tools |
||||
|
- `ci` modify CI configuration and scripts |
||||
|
- `types` type definition file changes |
||||
|
- `wip` in development |
||||
@ -0,0 +1,131 @@ |
|||||
|
<div align="center"> |
||||
|
<br> |
||||
|
<br> |
||||
|
<img src="./src/assets/images/logo.png" height="140" /> |
||||
|
<h3> Slash Admin </h3> |
||||
|
<p> |
||||
|
<p style="font-size: 14px"> |
||||
|
Slash Admin 是一款现代化的后台管理模板,基于 React 18、Vite、Ant Design 和 TypeScript 构建。它旨在帮助开发人员快速搭建功能强大的后台管理系统。 |
||||
|
</p> |
||||
|
<br /> |
||||
|
<br /> |
||||
|
<a href="https://admin.slashspaces.com/">Preview</a> |
||||
|
· |
||||
|
<a href="https://discord.gg/fXemAXVNDa">Discord</a> |
||||
|
· |
||||
|
<a href="https://docs-admin.slashspaces.com/">Document</a> |
||||
|
<br /> |
||||
|
<br /> |
||||
|
<a href="https://trendshift.io/repositories/6387" target="_blank"><img src="https://trendshift.io/api/badge/repositories/6387" alt="d3george%2Fslash-admin | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a> |
||||
|
</div> |
||||
|
|
||||
|
**中文** | [English](./README.md) |
||||
|
|
||||
|
## 赞助 |
||||
|
<div style="display: flex; gap: 50px"> |
||||
|
<img style="width:300px" src="https://d3george.github.io/github-static/pay/weixin.jpg" > |
||||
|
<img style="width:280px" src="https://d3george.github.io/github-static/pay/buymeacoffee.png" /> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
## 预览 |
||||
|
+ https://admin.slashspaces.com/ |
||||
|
|
||||
|
|| |
||||
|
| ----------------------------------------------------------------- | ------------------------------------------------------------------- | |
||||
|
|| |
||||
|
## 特性 |
||||
|
|
||||
|
- 使用 React 18 hooks 进行构建。 |
||||
|
- 基于 Vite 进行快速开发和热模块替换。 |
||||
|
- 集成 Ant Design,提供丰富的 UI 组件和设计模式。 |
||||
|
- 使用 TypeScript 编写,提供类型安全性和更好的开发体验。 |
||||
|
- 响应式设计,适应各种屏幕尺寸和设备。 |
||||
|
- 灵活的路由配置,支持多级嵌套路由。 |
||||
|
- 集成权限管理,根据用户角色控制页面访问权限。 |
||||
|
- 集成国际化支持,轻松切换多语言。 |
||||
|
- 集成常见的后台管理功能,如用户管理、角色管理、权限管理等。 |
||||
|
- 可定制的主题和样式,以满足您的品牌需求。 |
||||
|
- 基于 MSW 和 Faker.js 的Mock方案 |
||||
|
- 使用 Zustand 进行状态管理 |
||||
|
- 使用 React-Query 进行数据获取 |
||||
|
|
||||
|
## 快速开始 |
||||
|
|
||||
|
### 获取项目代码 |
||||
|
|
||||
|
```bash |
||||
|
git clone https://github.com/d3george/slash-admin.git |
||||
|
``` |
||||
|
|
||||
|
### 安装依赖 |
||||
|
|
||||
|
在项目根目录下运行以下命令安装项目依赖: |
||||
|
|
||||
|
```bash |
||||
|
pnpm install |
||||
|
``` |
||||
|
|
||||
|
### 启动开发服务器 |
||||
|
|
||||
|
运行以下命令以启动开发服务器: |
||||
|
|
||||
|
```bash |
||||
|
pnpm dev |
||||
|
``` |
||||
|
|
||||
|
访问 [http://localhost:3001](http://localhost:3001) 查看您的应用程序。 |
||||
|
|
||||
|
### 构建生产版本 |
||||
|
|
||||
|
运行以下命令以构建生产版本: |
||||
|
|
||||
|
```bash |
||||
|
pnpm build |
||||
|
``` |
||||
|
|
||||
|
构建后的文件将位于 `dist` 目录中。 |
||||
|
|
||||
|
## 容器化部署 |
||||
|
|
||||
|
### 构建镜像并运行容器 |
||||
|
#### 构建镜像 |
||||
|
在终端中进入项目根目录,并执行以下命令来构建 Docker 镜像: |
||||
|
``` |
||||
|
docker build -t your-image-name . |
||||
|
``` |
||||
|
确保将 `your-image-name` 替换为你自己的镜像名称 |
||||
|
|
||||
|
#### 运行容器 |
||||
|
使用以下命令在 Docker 容器中运行你的应用: |
||||
|
``` |
||||
|
docker run -p 3001:80 your-image-name |
||||
|
``` |
||||
|
这将在容器的端口 `80` (暴露在`Dockerfile`中) 上运行你的应用,并将其映射到你主机的端口 `3001` 上。 |
||||
|
|
||||
|
现在,你可以通过访问 http://localhost:3001 来查看部署的应用。 |
||||
|
|
||||
|
|
||||
|
### 使用docker-compose.yaml |
||||
|
在终端中进入项目根目录,并执行以下命令来启动 Docker Compose: |
||||
|
``` |
||||
|
docker-compose up -d |
||||
|
``` |
||||
|
Docker Compose 根据`docker-compose.yaml`定义的配置构建镜像并在后台运行容器. |
||||
|
|
||||
|
容器运行成功后,同样可以通过访问 http://localhost:3001来查看部署的应用。 |
||||
|
|
||||
|
参考[.commitlint.config.js](./commitlint.config.js) |
||||
|
|
||||
|
- `feat` 新功能 |
||||
|
- `fix` 修复bug |
||||
|
- `docs` 文档注释 |
||||
|
- `style` 代码格式(不影响代码运行的变动) |
||||
|
- `refactor` 重构 |
||||
|
- `perf` 性能优化 |
||||
|
- `revert` 回滚commit |
||||
|
- `test` 测试相关 |
||||
|
- `chore` 构建过程或辅助工具的变动 |
||||
|
- `ci` 修改CI配置、脚本 |
||||
|
- `types` 类型定义文件修改 |
||||
|
- `wip` 开发中 |
||||
@ -0,0 +1,44 @@ |
|||||
|
{ |
||||
|
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", |
||||
|
"vcs": { |
||||
|
"enabled": true, |
||||
|
"clientKind": "git", |
||||
|
"useIgnoreFile": true, |
||||
|
"defaultBranch": "main" |
||||
|
}, |
||||
|
"files": { |
||||
|
"ignoreUnknown": false, |
||||
|
"ignore": ["public", ".vscode", "src/api/gen"] |
||||
|
}, |
||||
|
"formatter": { |
||||
|
"enabled": true, |
||||
|
"lineWidth": 120, |
||||
|
"indentStyle": "tab" |
||||
|
}, |
||||
|
"organizeImports": { |
||||
|
"enabled": true |
||||
|
}, |
||||
|
"linter": { |
||||
|
"enabled": true, |
||||
|
"rules": { |
||||
|
"recommended": true, |
||||
|
"suspicious": { |
||||
|
"noExplicitAny": "off" |
||||
|
}, |
||||
|
"a11y": { |
||||
|
"useKeyWithClickEvents": "off" |
||||
|
}, |
||||
|
"complexity": { |
||||
|
"noForEach": "off" |
||||
|
}, |
||||
|
"correctness": { |
||||
|
"useExhaustiveDependencies": "off" |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
"javascript": { |
||||
|
"formatter": { |
||||
|
"quoteStyle": "double" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
services: |
||||
|
slash: |
||||
|
build: |
||||
|
context: . |
||||
|
ports: |
||||
|
- "3001:80" |
||||
|
restart: always |
||||
@ -0,0 +1,13 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="en"> |
||||
|
<head> |
||||
|
<meta charset="UTF-8" /> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||
|
<title>Slash Admin</title> |
||||
|
</head> |
||||
|
<body> |
||||
|
<noscript>You need to enable JavaScript to run this app.</noscript> |
||||
|
<div id="root"></div> |
||||
|
<script type="module" src="/src/main.tsx"></script> |
||||
|
</body> |
||||
|
</html> |
||||
@ -0,0 +1,26 @@ |
|||||
|
# SKIP CI in commit message to skip hooks |
||||
|
skip_output: |
||||
|
- meta |
||||
|
- success |
||||
|
- summary |
||||
|
|
||||
|
pre-commit: |
||||
|
parallel: true |
||||
|
commands: |
||||
|
format: |
||||
|
glob: "*.{js,jsx,ts,tsx,json,md}" |
||||
|
run: npx @biomejs/biome format --write --no-errors-on-unmatched {staged_files} |
||||
|
stage_fixed: true |
||||
|
lint: |
||||
|
glob: "*.{js,jsx,ts,tsx}" |
||||
|
run: npx @biomejs/biome lint --no-errors-on-unmatched {staged_files} |
||||
|
check-types: |
||||
|
glob: "*.{ts,tsx}" |
||||
|
run: npx tsc --noEmit |
||||
|
|
||||
|
commit-msg: |
||||
|
commands: |
||||
|
commitlint: |
||||
|
run: npx commitlint --edit {1} |
||||
|
# 允许空提交信息 |
||||
|
skip: merge|rebase |
||||
@ -0,0 +1,18 @@ |
|||||
|
import { defineConfig } from "@hey-api/openapi-ts"; |
||||
|
import { defaultPlugins } from "@hey-api/openapi-ts"; |
||||
|
export default defineConfig({ |
||||
|
client: "@hey-api/client-axios", |
||||
|
input: "http://192.168.31.246:30001/swagger/v1/swagger.json", |
||||
|
output: { |
||||
|
format: "biome", |
||||
|
lint: "biome", |
||||
|
path: "src/api/gen", |
||||
|
}, |
||||
|
plugins: [ |
||||
|
...defaultPlugins, |
||||
|
{ |
||||
|
enums: "typescript", |
||||
|
name: "@hey-api/typescript", |
||||
|
}, |
||||
|
], |
||||
|
}); |
||||
@ -0,0 +1,117 @@ |
|||||
|
{ |
||||
|
"name": "slash-admin", |
||||
|
"private": true, |
||||
|
"version": "0.0.0", |
||||
|
"type": "module", |
||||
|
"homepage": "https://github.com/d3george/slash-admin", |
||||
|
"scripts": { |
||||
|
"dev": "vite", |
||||
|
"build": "tsc && vite build", |
||||
|
"preview": "vite preview", |
||||
|
"preinstall": "lefthook install", |
||||
|
"gen-api": "openapi-ts" |
||||
|
}, |
||||
|
"dependencies": { |
||||
|
"@ant-design/cssinjs": "^1.17.2", |
||||
|
"@ant-design/icons": "^5.2.6", |
||||
|
"@ant-design/pro-table": "^3.18.3", |
||||
|
"@fullcalendar/common": "^5.11.5", |
||||
|
"@fullcalendar/core": "^6.1.9", |
||||
|
"@fullcalendar/daygrid": "^6.1.9", |
||||
|
"@fullcalendar/interaction": "^6.1.9", |
||||
|
"@fullcalendar/list": "^6.1.9", |
||||
|
"@fullcalendar/react": "^6.1.9", |
||||
|
"@fullcalendar/timegrid": "^6.1.9", |
||||
|
"@fullcalendar/timeline": "^6.1.9", |
||||
|
"@hey-api/client-axios": "^0.2.12", |
||||
|
"@iconify/react": "^4.1.1", |
||||
|
"@microsoft/signalr": "^8.0.7", |
||||
|
"@tanstack/react-query": "^5.50.1", |
||||
|
"@tanstack/react-query-devtools": "^5.50.1", |
||||
|
"@vanilla-extract/css": "^1.17.0", |
||||
|
"@vanilla-extract/vite-plugin": "^4.0.19", |
||||
|
"@vercel/analytics": "^1.2.2", |
||||
|
"@vitejs/plugin-react": "^4.1.0", |
||||
|
"antd": "^5.9.3", |
||||
|
"apexcharts": "^3.43.0", |
||||
|
"autosuggest-highlight": "^3.3.4", |
||||
|
"axios": "^1.5.1", |
||||
|
"classnames": "^2.3.2", |
||||
|
"clsx": "^2.1.1", |
||||
|
"color": "^4.2.3", |
||||
|
"dayjs": "^1.11.10", |
||||
|
"defu": "^6.1.4", |
||||
|
"framer-motion": "^10.16.4", |
||||
|
"highlight.js": "^11.9.0", |
||||
|
"i18next": "^23.5.1", |
||||
|
"i18next-browser-languagedetector": "^7.1.0", |
||||
|
"json-edit-react": "^1.19.2", |
||||
|
"nprogress": "^0.2.0", |
||||
|
"numeral": "^2.0.6", |
||||
|
"ramda": "^0.29.1", |
||||
|
"react": "18.2.0", |
||||
|
"react-apexcharts": "^1.4.1", |
||||
|
"react-beautiful-dnd": "^13.1.1", |
||||
|
"react-dom": "18.2.0", |
||||
|
"react-error-boundary": "^4.0.13", |
||||
|
"react-helmet-async": "^2.0.5", |
||||
|
"react-i18next": "^13.2.2", |
||||
|
"react-icons": "^4.11.0", |
||||
|
"react-markdown": "^8.0.7", |
||||
|
"react-organizational-chart": "^2.2.1", |
||||
|
"react-quill": "^2.0.0", |
||||
|
"react-router": "^7.0.2", |
||||
|
"react-use": "^17.4.0", |
||||
|
"rehype-highlight": "^6.0.0", |
||||
|
"rehype-raw": "^6.1.1", |
||||
|
"remark-gfm": "^3.0.1", |
||||
|
"reset-css": "^5.0.2", |
||||
|
"screenfull": "^6.0.2", |
||||
|
"simplebar-react": "^3.2.4", |
||||
|
"sonner": "^1.7.0", |
||||
|
"styled-components": "^6.0.9", |
||||
|
"tailwind-merge": "^2.5.4", |
||||
|
"zustand": "^4.4.3" |
||||
|
}, |
||||
|
"devDependencies": { |
||||
|
"@biomejs/biome": "1.9.4", |
||||
|
"@commitlint/cli": "^17.7.2", |
||||
|
"@commitlint/config-conventional": "^17.7.0", |
||||
|
"@faker-js/faker": "^8.1.0", |
||||
|
"@hey-api/openapi-ts": "^0.59.1", |
||||
|
"@types/autosuggest-highlight": "^3.2.0", |
||||
|
"@types/color": "^3.0.4", |
||||
|
"@types/nprogress": "^0.2.1", |
||||
|
"@types/numeral": "^2.0.3", |
||||
|
"@types/ramda": "^0.29.6", |
||||
|
"@types/react": "^18.2.28", |
||||
|
"@types/react-beautiful-dnd": "^13.1.6", |
||||
|
"@types/react-dom": "^18.2.13", |
||||
|
"@types/styled-components": "^5.1.28", |
||||
|
"autoprefixer": "^10.4.16", |
||||
|
"axios-mock-adapter": "^2.1.0", |
||||
|
"lefthook": "^1.8.2", |
||||
|
"msw": "^2.4.9", |
||||
|
"postcss": "^8.4.31", |
||||
|
"postcss-import": "^15.1.0", |
||||
|
"postcss-nesting": "^11.3.0", |
||||
|
"rollup-plugin-visualizer": "^5.9.2", |
||||
|
"tailwindcss": "^3.3.3", |
||||
|
"ts-node": "^10.9.1", |
||||
|
"typescript": "^5.2.2", |
||||
|
"vite": "^5.4.9", |
||||
|
"vite-plugin-svg-icons": "^2.0.1", |
||||
|
"vite-tsconfig-paths": "^5.0.1", |
||||
|
"vitest": "^2.1.8" |
||||
|
}, |
||||
|
"engines": { |
||||
|
"node": "20.*" |
||||
|
}, |
||||
|
"packageManager": "pnpm@9.1.0", |
||||
|
"msw": { |
||||
|
"workerDirectory": "public" |
||||
|
}, |
||||
|
"commitlint": { |
||||
|
"extends": ["@commitlint/config-conventional"] |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
export default { |
||||
|
plugins: { |
||||
|
"postcss-import": {}, |
||||
|
"tailwindcss/nesting": "postcss-nesting", |
||||
|
tailwindcss: {}, |
||||
|
autoprefixer: {}, |
||||
|
}, |
||||
|
}; |
||||
@ -0,0 +1,295 @@ |
|||||
|
/* eslint-disable */ |
||||
|
/* tslint:disable */ |
||||
|
|
||||
|
/** |
||||
|
* Mock Service Worker. |
||||
|
* @see https://github.com/mswjs/msw
|
||||
|
* - Please do NOT modify this file. |
||||
|
* - Please do NOT serve this file on production. |
||||
|
*/ |
||||
|
|
||||
|
const PACKAGE_VERSION = '2.6.4' |
||||
|
const INTEGRITY_CHECKSUM = 'ca7800994cc8bfb5eb961e037c877074' |
||||
|
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') |
||||
|
const activeClientIds = new Set() |
||||
|
|
||||
|
self.addEventListener('install', function () { |
||||
|
self.skipWaiting() |
||||
|
}) |
||||
|
|
||||
|
self.addEventListener('activate', function (event) { |
||||
|
event.waitUntil(self.clients.claim()) |
||||
|
}) |
||||
|
|
||||
|
self.addEventListener('message', async function (event) { |
||||
|
const clientId = event.source.id |
||||
|
|
||||
|
if (!clientId || !self.clients) { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
const client = await self.clients.get(clientId) |
||||
|
|
||||
|
if (!client) { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
const allClients = await self.clients.matchAll({ |
||||
|
type: 'window', |
||||
|
}) |
||||
|
|
||||
|
switch (event.data) { |
||||
|
case 'KEEPALIVE_REQUEST': { |
||||
|
sendToClient(client, { |
||||
|
type: 'KEEPALIVE_RESPONSE', |
||||
|
}) |
||||
|
break |
||||
|
} |
||||
|
|
||||
|
case 'INTEGRITY_CHECK_REQUEST': { |
||||
|
sendToClient(client, { |
||||
|
type: 'INTEGRITY_CHECK_RESPONSE', |
||||
|
payload: { |
||||
|
packageVersion: PACKAGE_VERSION, |
||||
|
checksum: INTEGRITY_CHECKSUM, |
||||
|
}, |
||||
|
}) |
||||
|
break |
||||
|
} |
||||
|
|
||||
|
case 'MOCK_ACTIVATE': { |
||||
|
activeClientIds.add(clientId) |
||||
|
|
||||
|
sendToClient(client, { |
||||
|
type: 'MOCKING_ENABLED', |
||||
|
payload: { |
||||
|
client: { |
||||
|
id: client.id, |
||||
|
frameType: client.frameType, |
||||
|
}, |
||||
|
}, |
||||
|
}) |
||||
|
break |
||||
|
} |
||||
|
|
||||
|
case 'MOCK_DEACTIVATE': { |
||||
|
activeClientIds.delete(clientId) |
||||
|
break |
||||
|
} |
||||
|
|
||||
|
case 'CLIENT_CLOSED': { |
||||
|
activeClientIds.delete(clientId) |
||||
|
|
||||
|
const remainingClients = allClients.filter((client) => { |
||||
|
return client.id !== clientId |
||||
|
}) |
||||
|
|
||||
|
// Unregister itself when there are no more clients
|
||||
|
if (remainingClients.length === 0) { |
||||
|
self.registration.unregister() |
||||
|
} |
||||
|
|
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
self.addEventListener('fetch', function (event) { |
||||
|
const { request } = event |
||||
|
|
||||
|
// Bypass navigation requests.
|
||||
|
if (request.mode === 'navigate') { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
// Opening the DevTools triggers the "only-if-cached" request
|
||||
|
// that cannot be handled by the worker. Bypass such requests.
|
||||
|
if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
// Bypass all requests when there are no active clients.
|
||||
|
// Prevents the self-unregistered worked from handling requests
|
||||
|
// after it's been deleted (still remains active until the next reload).
|
||||
|
if (activeClientIds.size === 0) { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
// Generate unique request ID.
|
||||
|
const requestId = crypto.randomUUID() |
||||
|
event.respondWith(handleRequest(event, requestId)) |
||||
|
}) |
||||
|
|
||||
|
async function handleRequest(event, requestId) { |
||||
|
const client = await resolveMainClient(event) |
||||
|
const response = await getResponse(event, client, requestId) |
||||
|
|
||||
|
// Send back the response clone for the "response:*" life-cycle events.
|
||||
|
// Ensure MSW is active and ready to handle the message, otherwise
|
||||
|
// this message will pend indefinitely.
|
||||
|
if (client && activeClientIds.has(client.id)) { |
||||
|
;(async function () { |
||||
|
const responseClone = response.clone() |
||||
|
|
||||
|
sendToClient( |
||||
|
client, |
||||
|
{ |
||||
|
type: 'RESPONSE', |
||||
|
payload: { |
||||
|
requestId, |
||||
|
isMockedResponse: IS_MOCKED_RESPONSE in response, |
||||
|
type: responseClone.type, |
||||
|
status: responseClone.status, |
||||
|
statusText: responseClone.statusText, |
||||
|
body: responseClone.body, |
||||
|
headers: Object.fromEntries(responseClone.headers.entries()), |
||||
|
}, |
||||
|
}, |
||||
|
[responseClone.body], |
||||
|
) |
||||
|
})() |
||||
|
} |
||||
|
|
||||
|
return response |
||||
|
} |
||||
|
|
||||
|
// Resolve the main client for the given event.
|
||||
|
// Client that issues a request doesn't necessarily equal the client
|
||||
|
// that registered the worker. It's with the latter the worker should
|
||||
|
// communicate with during the response resolving phase.
|
||||
|
async function resolveMainClient(event) { |
||||
|
const client = await self.clients.get(event.clientId) |
||||
|
|
||||
|
if (activeClientIds.has(event.clientId)) { |
||||
|
return client |
||||
|
} |
||||
|
|
||||
|
if (client?.frameType === 'top-level') { |
||||
|
return client |
||||
|
} |
||||
|
|
||||
|
const allClients = await self.clients.matchAll({ |
||||
|
type: 'window', |
||||
|
}) |
||||
|
|
||||
|
return allClients |
||||
|
.filter((client) => { |
||||
|
// Get only those clients that are currently visible.
|
||||
|
return client.visibilityState === 'visible' |
||||
|
}) |
||||
|
.find((client) => { |
||||
|
// Find the client ID that's recorded in the
|
||||
|
// set of clients that have registered the worker.
|
||||
|
return activeClientIds.has(client.id) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
async function getResponse(event, client, requestId) { |
||||
|
const { request } = event |
||||
|
|
||||
|
// Clone the request because it might've been already used
|
||||
|
// (i.e. its body has been read and sent to the client).
|
||||
|
const requestClone = request.clone() |
||||
|
|
||||
|
function passthrough() { |
||||
|
// Cast the request headers to a new Headers instance
|
||||
|
// so the headers can be manipulated with.
|
||||
|
const headers = new Headers(requestClone.headers) |
||||
|
|
||||
|
// Remove the "accept" header value that marked this request as passthrough.
|
||||
|
// This prevents request alteration and also keeps it compliant with the
|
||||
|
// user-defined CORS policies.
|
||||
|
headers.delete('accept', 'msw/passthrough') |
||||
|
|
||||
|
return fetch(requestClone, { headers }) |
||||
|
} |
||||
|
|
||||
|
// Bypass mocking when the client is not active.
|
||||
|
if (!client) { |
||||
|
return passthrough() |
||||
|
} |
||||
|
|
||||
|
// Bypass initial page load requests (i.e. static assets).
|
||||
|
// The absence of the immediate/parent client in the map of the active clients
|
||||
|
// means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet
|
||||
|
// and is not ready to handle requests.
|
||||
|
if (!activeClientIds.has(client.id)) { |
||||
|
return passthrough() |
||||
|
} |
||||
|
|
||||
|
// Notify the client that a request has been intercepted.
|
||||
|
const requestBuffer = await request.arrayBuffer() |
||||
|
const clientMessage = await sendToClient( |
||||
|
client, |
||||
|
{ |
||||
|
type: 'REQUEST', |
||||
|
payload: { |
||||
|
id: requestId, |
||||
|
url: request.url, |
||||
|
mode: request.mode, |
||||
|
method: request.method, |
||||
|
headers: Object.fromEntries(request.headers.entries()), |
||||
|
cache: request.cache, |
||||
|
credentials: request.credentials, |
||||
|
destination: request.destination, |
||||
|
integrity: request.integrity, |
||||
|
redirect: request.redirect, |
||||
|
referrer: request.referrer, |
||||
|
referrerPolicy: request.referrerPolicy, |
||||
|
body: requestBuffer, |
||||
|
keepalive: request.keepalive, |
||||
|
}, |
||||
|
}, |
||||
|
[requestBuffer], |
||||
|
) |
||||
|
|
||||
|
switch (clientMessage.type) { |
||||
|
case 'MOCK_RESPONSE': { |
||||
|
return respondWithMock(clientMessage.data) |
||||
|
} |
||||
|
|
||||
|
case 'PASSTHROUGH': { |
||||
|
return passthrough() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return passthrough() |
||||
|
} |
||||
|
|
||||
|
function sendToClient(client, message, transferrables = []) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
const channel = new MessageChannel() |
||||
|
|
||||
|
channel.port1.onmessage = (event) => { |
||||
|
if (event.data && event.data.error) { |
||||
|
return reject(event.data.error) |
||||
|
} |
||||
|
|
||||
|
resolve(event.data) |
||||
|
} |
||||
|
|
||||
|
client.postMessage( |
||||
|
message, |
||||
|
[channel.port2].concat(transferrables.filter(Boolean)), |
||||
|
) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
async function respondWithMock(response) { |
||||
|
// Setting response status code to 0 is a no-op.
|
||||
|
// However, when responding with a "Response.error()", the produced Response
|
||||
|
// instance will have status code set to 0. Since it's not possible to create
|
||||
|
// a Response instance with status code 0, handle that use-case separately.
|
||||
|
if (response.status === 0) { |
||||
|
return Response.error() |
||||
|
} |
||||
|
|
||||
|
const mockedResponse = new Response(response.body, response) |
||||
|
|
||||
|
Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, { |
||||
|
value: true, |
||||
|
enumerable: true, |
||||
|
}) |
||||
|
|
||||
|
return mockedResponse |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
import { Helmet } from "react-helmet-async"; |
||||
|
|
||||
|
import Logo from "@/assets/images/logo.png"; |
||||
|
import Router from "@/router/index"; |
||||
|
|
||||
|
import { MotionLazy } from "./components/animate/motion-lazy"; |
||||
|
import Toast from "./components/toast"; |
||||
|
import { AntdAdapter } from "./theme/adapter/antd.adapter"; |
||||
|
import { ThemeProvider } from "./theme/theme-provider"; |
||||
|
import { useEffect } from "react"; |
||||
|
|
||||
|
import { useSetLocale } from "./store/localeI18nStore"; |
||||
|
import { useTranslation } from "react-i18next"; |
||||
|
import { getStringItem } from "./utils/storage"; |
||||
|
import { LocalEnum, StorageEnum } from "#/enum"; |
||||
|
import { useSessions } from "./hooks/abp/use-sessions"; |
||||
|
|
||||
|
function App() { |
||||
|
const { i18n } = useTranslation(); |
||||
|
const setLocale = useSetLocale(); |
||||
|
const defaultLng = getStringItem(StorageEnum.I18N) || LocalEnum.en_US; |
||||
|
useSessions(); |
||||
|
useEffect(() => { |
||||
|
async function initializeI18n() { |
||||
|
await setLocale(defaultLng as LocalEnum, i18n); |
||||
|
} |
||||
|
initializeI18n(); //触发abp语言包加载
|
||||
|
}, [defaultLng, i18n, setLocale]); |
||||
|
return ( |
||||
|
<ThemeProvider adapters={[AntdAdapter]}> |
||||
|
<MotionLazy> |
||||
|
<Helmet> |
||||
|
<title>Slash Admin</title> |
||||
|
<link rel="icon" href={Logo} /> |
||||
|
</Helmet> |
||||
|
<Toast /> |
||||
|
|
||||
|
<Router /> |
||||
|
</MotionLazy> |
||||
|
</ThemeProvider> |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
export default App; |
||||
@ -0,0 +1,610 @@ |
|||||
|
import useUserStore from "@/store/userStore"; |
||||
|
import { faker } from "@faker-js/faker"; |
||||
|
|
||||
|
import { BasicStatus, PermissionType } from "#/enum"; |
||||
|
/** |
||||
|
* Organization data mock |
||||
|
*/ |
||||
|
export const ORG_LIST = [ |
||||
|
{ |
||||
|
id: "1", |
||||
|
name: "East China Branch", |
||||
|
status: "enable", |
||||
|
desc: faker.lorem.words(), |
||||
|
order: 1, |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "1-1", |
||||
|
name: "R&D Department", |
||||
|
status: "disable", |
||||
|
desc: "", |
||||
|
order: 1, |
||||
|
}, |
||||
|
{ |
||||
|
id: "1-2", |
||||
|
name: "Marketing Department", |
||||
|
status: "enable", |
||||
|
desc: "", |
||||
|
order: 2, |
||||
|
}, |
||||
|
{ |
||||
|
id: "1-3", |
||||
|
name: "Finance Department", |
||||
|
status: "enable", |
||||
|
desc: "", |
||||
|
order: 3, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
{ |
||||
|
id: "2", |
||||
|
name: "South China Branch", |
||||
|
status: "enable", |
||||
|
desc: faker.lorem.words(), |
||||
|
order: 2, |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "2-1", |
||||
|
name: "R&D Department", |
||||
|
status: "disable", |
||||
|
desc: "", |
||||
|
order: 1, |
||||
|
}, |
||||
|
{ |
||||
|
id: "2-2", |
||||
|
name: "Marketing Department", |
||||
|
status: "enable", |
||||
|
desc: "", |
||||
|
order: 2, |
||||
|
}, |
||||
|
{ |
||||
|
id: "2-3", |
||||
|
name: "Finance Department", |
||||
|
status: "enable", |
||||
|
desc: "", |
||||
|
order: 3, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
/** |
||||
|
* User permission mock |
||||
|
*/ |
||||
|
const DASHBOARD_PERMISSION = { |
||||
|
id: "9100714781927703", |
||||
|
parentId: "", |
||||
|
label: "sys.menu.dashboard", |
||||
|
name: "Dashboard", |
||||
|
icon: "ic-analysis", |
||||
|
type: PermissionType.CATALOGUE, |
||||
|
route: "dashboard", |
||||
|
order: 1, |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "8426999229400979", |
||||
|
parentId: "9100714781927703", |
||||
|
label: "sys.menu.workbench", |
||||
|
name: "Workbench", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "workbench", |
||||
|
component: "/dashboard/workbench/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "9710971640510357", |
||||
|
parentId: "9100714781927703", |
||||
|
label: "sys.menu.analysis", |
||||
|
name: "Analysis", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "analysis", |
||||
|
component: "/dashboard/analysis/index.tsx", |
||||
|
}, |
||||
|
], |
||||
|
}; |
||||
|
const MANAGEMENT_PERMISSION = { |
||||
|
id: "0901673425580518", |
||||
|
parentId: "", |
||||
|
label: "sys.menu.management", |
||||
|
name: "Management", |
||||
|
icon: "ic-management", |
||||
|
type: PermissionType.CATALOGUE, |
||||
|
route: "management", |
||||
|
order: 2, |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "2781684678535711", |
||||
|
parentId: "0901673425580518", |
||||
|
label: "sys.menu.user.index", |
||||
|
name: "User", |
||||
|
type: PermissionType.CATALOGUE, |
||||
|
route: "user", |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "4754063958766648", |
||||
|
parentId: "2781684678535711", |
||||
|
label: "sys.menu.user.profile", |
||||
|
name: "Profile", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "profile", |
||||
|
component: "/management/user/profile/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "2516598794787938", |
||||
|
parentId: "2781684678535711", |
||||
|
label: "sys.menu.user.account", |
||||
|
name: "Account", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "account", |
||||
|
component: "/management/user/account/index.tsx", |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
{ |
||||
|
id: "0249937641030250", |
||||
|
parentId: "0901673425580518", |
||||
|
label: "sys.menu.system.index", |
||||
|
name: "System", |
||||
|
type: PermissionType.CATALOGUE, |
||||
|
route: "system", |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "1985890042972842", |
||||
|
parentId: "0249937641030250", |
||||
|
label: "sys.menu.system.organization", |
||||
|
name: "Organization", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "organization", |
||||
|
component: "/management/system/organization/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "4359580910369984", |
||||
|
parentId: "0249937641030250", |
||||
|
label: "sys.menu.system.permission", |
||||
|
name: "Permission", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "permission", |
||||
|
component: "/management/system/permission/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "1689241785490759", |
||||
|
parentId: "0249937641030250", |
||||
|
label: "sys.menu.system.role", |
||||
|
name: "Role", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "role", |
||||
|
component: "/management/system/role/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "0157880245365433", |
||||
|
parentId: "0249937641030250", |
||||
|
label: "sys.menu.system.user", |
||||
|
name: "User", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "user", |
||||
|
component: "/management/system/user/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "0157880245365434", |
||||
|
parentId: "0249937641030250", |
||||
|
label: "sys.menu.system.user_detail", |
||||
|
name: "User Detail", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "user/:id", |
||||
|
component: "/management/system/user/detail.tsx", |
||||
|
hide: true, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
], |
||||
|
}; |
||||
|
const COMPONENTS_PERMISSION = { |
||||
|
id: "2271615060673773", |
||||
|
parentId: "", |
||||
|
label: "sys.menu.components", |
||||
|
name: "Components", |
||||
|
icon: "solar:widget-5-bold-duotone", |
||||
|
type: PermissionType.CATALOGUE, |
||||
|
route: "components", |
||||
|
order: 3, |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "2478488238255411", |
||||
|
parentId: "2271615060673773", |
||||
|
label: "sys.menu.icon", |
||||
|
name: "Icon", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "icon", |
||||
|
component: "/components/icon/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "6755238352318767", |
||||
|
parentId: "2271615060673773", |
||||
|
label: "sys.menu.animate", |
||||
|
name: "Animate", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "animate", |
||||
|
component: "/components/animate/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "9992476513546805", |
||||
|
parentId: "2271615060673773", |
||||
|
label: "sys.menu.scroll", |
||||
|
name: "Scroll", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "scroll", |
||||
|
component: "/components/scroll/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "1755562695856395", |
||||
|
parentId: "2271615060673773", |
||||
|
label: "sys.menu.markdown", |
||||
|
name: "Markdown", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "markdown", |
||||
|
component: "/components/markdown/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "2122547769468069", |
||||
|
parentId: "2271615060673773", |
||||
|
label: "sys.menu.editor", |
||||
|
name: "Editor", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "editor", |
||||
|
component: "/components/editor/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "2501920741714350", |
||||
|
parentId: "2271615060673773", |
||||
|
label: "sys.menu.i18n", |
||||
|
name: "Multi Language", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "i18n", |
||||
|
component: "/components/multi-language/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "2013577074467956", |
||||
|
parentId: "2271615060673773", |
||||
|
label: "sys.menu.upload", |
||||
|
name: "upload", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "Upload", |
||||
|
component: "/components/upload/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "7749726274771764", |
||||
|
parentId: "2271615060673773", |
||||
|
label: "sys.menu.chart", |
||||
|
name: "Chart", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "chart", |
||||
|
component: "/components/chart/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "2013577074467957", |
||||
|
parentId: "2271615060673773", |
||||
|
label: "sys.menu.toast", |
||||
|
name: "Toast", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "toast", |
||||
|
component: "/components/toast/index.tsx", |
||||
|
}, |
||||
|
], |
||||
|
}; |
||||
|
const FUNCTIONS_PERMISSION = { |
||||
|
id: "8132044808088488", |
||||
|
parentId: "", |
||||
|
label: "sys.menu.functions", |
||||
|
name: "functions", |
||||
|
icon: "solar:plain-2-bold-duotone", |
||||
|
type: PermissionType.CATALOGUE, |
||||
|
route: "functions", |
||||
|
order: 4, |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "3667930780705750", |
||||
|
parentId: "8132044808088488", |
||||
|
label: "sys.menu.clipboard", |
||||
|
name: "Clipboard", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "clipboard", |
||||
|
component: "/functions/clipboard/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "3667930780705751", |
||||
|
parentId: "8132044808088488", |
||||
|
label: "sys.menu.token_expired", |
||||
|
name: "Token Expired", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "token-expired", |
||||
|
component: "/functions/token-expired/index.tsx", |
||||
|
}, |
||||
|
], |
||||
|
}; |
||||
|
const MENU_LEVEL_PERMISSION = { |
||||
|
id: "0194818428516575", |
||||
|
parentId: "", |
||||
|
label: "sys.menu.menulevel.index", |
||||
|
name: "Menu Level", |
||||
|
icon: "ic-menulevel", |
||||
|
type: PermissionType.CATALOGUE, |
||||
|
route: "menu-level", |
||||
|
order: 5, |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "0144431332471389", |
||||
|
parentId: "0194818428516575", |
||||
|
label: "sys.menu.menulevel.1a", |
||||
|
name: "Menu Level 1a", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "menu-level-1a", |
||||
|
component: "/menu-level/menu-level-1a/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "7572529636800586", |
||||
|
parentId: "0194818428516575", |
||||
|
label: "sys.menu.menulevel.1b.index", |
||||
|
name: "Menu Level 1b", |
||||
|
type: PermissionType.CATALOGUE, |
||||
|
route: "menu-level-1b", |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "3653745576583237", |
||||
|
parentId: "7572529636800586", |
||||
|
label: "sys.menu.menulevel.1b.2a", |
||||
|
name: "Menu Level 2a", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "menu-level-2a", |
||||
|
component: "/menu-level/menu-level-1b/menu-level-2a/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "4873136353891364", |
||||
|
parentId: "7572529636800586", |
||||
|
label: "sys.menu.menulevel.1b.2b.index", |
||||
|
name: "Menu Level 2b", |
||||
|
type: PermissionType.CATALOGUE, |
||||
|
route: "menu-level-2b", |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "4233029726998055", |
||||
|
parentId: "4873136353891364", |
||||
|
label: "sys.menu.menulevel.1b.2b.3a", |
||||
|
name: "Menu Level 3a", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "menu-level-3a", |
||||
|
component: "/menu-level/menu-level-1b/menu-level-2b/menu-level-3a/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "3298034742548454", |
||||
|
parentId: "4873136353891364", |
||||
|
label: "sys.menu.menulevel.1b.2b.3b", |
||||
|
name: "Menu Level 3b", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "menu-level-3b", |
||||
|
component: "/menu-level/menu-level-1b/menu-level-2b/menu-level-3b/index.tsx", |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
], |
||||
|
}; |
||||
|
const ERRORS_PERMISSION = { |
||||
|
id: "9406067785553476", |
||||
|
parentId: "", |
||||
|
label: "sys.menu.error.index", |
||||
|
name: "Error", |
||||
|
icon: "bxs:error-alt", |
||||
|
type: PermissionType.CATALOGUE, |
||||
|
route: "error", |
||||
|
order: 6, |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "8557056851997154", |
||||
|
parentId: "9406067785553476", |
||||
|
label: "sys.menu.error.403", |
||||
|
name: "403", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "403", |
||||
|
component: "/sys/error/Page403.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "5095669208159005", |
||||
|
parentId: "9406067785553476", |
||||
|
label: "sys.menu.error.404", |
||||
|
name: "404", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "404", |
||||
|
component: "/sys/error/Page404.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "0225992135973772", |
||||
|
parentId: "9406067785553476", |
||||
|
label: "sys.menu.error.500", |
||||
|
name: "500", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "500", |
||||
|
component: "/sys/error/Page500.tsx", |
||||
|
}, |
||||
|
], |
||||
|
}; |
||||
|
const OTHERS_PERMISSION = [ |
||||
|
{ |
||||
|
id: "3981225257359246", |
||||
|
parentId: "", |
||||
|
label: "sys.menu.calendar", |
||||
|
name: "Calendar", |
||||
|
icon: "solar:calendar-bold-duotone", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "calendar", |
||||
|
component: "/sys/others/calendar/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "3513985683886393", |
||||
|
parentId: "", |
||||
|
label: "sys.menu.kanban", |
||||
|
name: "kanban", |
||||
|
icon: "solar:clipboard-bold-duotone", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "kanban", |
||||
|
component: "/sys/others/kanban/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "5455837930804461", |
||||
|
parentId: "", |
||||
|
label: "sys.menu.disabled", |
||||
|
name: "Disabled", |
||||
|
icon: "ic_disabled", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "disabled", |
||||
|
status: BasicStatus.DISABLE, |
||||
|
component: "/sys/others/calendar/index.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "7728048658221587", |
||||
|
parentId: "", |
||||
|
label: "sys.menu.label", |
||||
|
name: "Label", |
||||
|
icon: "ic_label", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "label", |
||||
|
newFeature: true, |
||||
|
component: "/sys/others/blank.tsx", |
||||
|
}, |
||||
|
{ |
||||
|
id: "5733704222120995", |
||||
|
parentId: "", |
||||
|
label: "sys.menu.frame", |
||||
|
name: "Frame", |
||||
|
icon: "ic_external", |
||||
|
type: PermissionType.CATALOGUE, |
||||
|
route: "frame", |
||||
|
children: [ |
||||
|
{ |
||||
|
id: "9884486809510480", |
||||
|
parentId: "5733704222120995", |
||||
|
label: "sys.menu.external_link", |
||||
|
name: "External Link", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "external_link", |
||||
|
hideTab: true, |
||||
|
component: "/sys/others/iframe/external-link.tsx", |
||||
|
frameSrc: "https://ant.design/", |
||||
|
}, |
||||
|
{ |
||||
|
id: "9299640886731819", |
||||
|
parentId: "5733704222120995", |
||||
|
label: "sys.menu.iframe", |
||||
|
name: "Iframe", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "frame", |
||||
|
component: "/sys/others/iframe/index.tsx", |
||||
|
frameSrc: "https://ant.design/", |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
{ |
||||
|
id: "0941594969900756", |
||||
|
parentId: "", |
||||
|
label: "sys.menu.blank", |
||||
|
name: "Disabled", |
||||
|
icon: "ic_blank", |
||||
|
type: PermissionType.MENU, |
||||
|
route: "blank", |
||||
|
component: "/sys/others/blank.tsx", |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
export const PERMISSION_LIST = [ |
||||
|
DASHBOARD_PERMISSION, |
||||
|
MANAGEMENT_PERMISSION, |
||||
|
COMPONENTS_PERMISSION, |
||||
|
FUNCTIONS_PERMISSION, |
||||
|
MENU_LEVEL_PERMISSION, |
||||
|
ERRORS_PERMISSION, |
||||
|
...OTHERS_PERMISSION, |
||||
|
]; |
||||
|
|
||||
|
/** |
||||
|
* User role mock |
||||
|
*/ |
||||
|
const ADMIN_ROLE = { |
||||
|
id: "4281707933534332", |
||||
|
name: "Admin", |
||||
|
label: "admin", |
||||
|
status: BasicStatus.ENABLE, |
||||
|
order: 1, |
||||
|
desc: "Super Admin", |
||||
|
permission: PERMISSION_LIST, |
||||
|
}; |
||||
|
const TEST_ROLE = { |
||||
|
id: "9931665660771476", |
||||
|
name: "Test", |
||||
|
label: "test", |
||||
|
status: BasicStatus.ENABLE, |
||||
|
order: 2, |
||||
|
desc: "test", |
||||
|
permission: [DASHBOARD_PERMISSION, COMPONENTS_PERMISSION, FUNCTIONS_PERMISSION], |
||||
|
}; |
||||
|
export const ROLE_LIST = [ADMIN_ROLE, TEST_ROLE]; |
||||
|
|
||||
|
/** |
||||
|
* User data mock |
||||
|
*/ |
||||
|
export const DEFAULT_USER = { |
||||
|
id: "b34719e1-ce46-457e-9575-99505ecee828", |
||||
|
username: "admin", |
||||
|
email: faker.internet.email(), |
||||
|
avatar: faker.image.avatarGitHub(), |
||||
|
createdAt: faker.date.anytime(), |
||||
|
updatedAt: faker.date.recent(), |
||||
|
password: "1q2w3E*", |
||||
|
role: ADMIN_ROLE, |
||||
|
permissions: ADMIN_ROLE.permission, |
||||
|
desc: "", |
||||
|
homePath: "/", |
||||
|
token: "/", |
||||
|
realName: "", |
||||
|
userId: "", |
||||
|
}; |
||||
|
export const TEST_USER = { |
||||
|
id: "efaa20ea-4dc5-47ee-a200-8a899be29494", |
||||
|
username: "test", |
||||
|
password: "1q2w3E*", |
||||
|
email: faker.internet.email(), |
||||
|
avatar: faker.image.avatarGitHub(), |
||||
|
createdAt: faker.date.anytime(), |
||||
|
updatedAt: faker.date.recent(), |
||||
|
role: TEST_ROLE, |
||||
|
permissions: TEST_ROLE.permission, |
||||
|
desc: "", |
||||
|
homePath: "/", |
||||
|
token: "/", |
||||
|
realName: "", |
||||
|
userId: "", |
||||
|
}; |
||||
|
export const USER_LIST = [DEFAULT_USER, TEST_USER]; |
||||
|
|
||||
|
// * Hot update, updating user permissions, only effective in the development environment
|
||||
|
if (import.meta.hot) { |
||||
|
import.meta.hot.accept((newModule) => { |
||||
|
if (!newModule) return; |
||||
|
|
||||
|
const { DEFAULT_USER, TEST_USER, PERMISSION_LIST } = newModule; |
||||
|
|
||||
|
const { |
||||
|
userInfo, |
||||
|
actions: { setUserInfo }, |
||||
|
} = useUserStore.getState(); |
||||
|
|
||||
|
if (!userInfo?.username) return; |
||||
|
|
||||
|
const newUserInfo = userInfo.username === DEFAULT_USER.username ? DEFAULT_USER : TEST_USER; |
||||
|
|
||||
|
setUserInfo(newUserInfo); |
||||
|
|
||||
|
console.log("[HMR] User permissions updated:", { |
||||
|
username: newUserInfo.username, |
||||
|
permissions: newUserInfo.permissions, |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
import { http, HttpResponse } from "msw"; |
||||
|
|
||||
|
import { DemoApi } from "@/api/services/demoService"; |
||||
|
|
||||
|
const mockTokenExpired = http.post(`/api${DemoApi.TOKEN_EXPIRED}`, () => { |
||||
|
return new HttpResponse(null, { status: 401 }); |
||||
|
}); |
||||
|
|
||||
|
export default [mockTokenExpired]; |
||||
@ -0,0 +1,14 @@ |
|||||
|
import { http, HttpResponse } from "msw"; |
||||
|
|
||||
|
import { ORG_LIST } from "@/_mock/assets"; |
||||
|
import { OrgApi } from "@/api/services/orgService"; |
||||
|
|
||||
|
const orgList = http.get(`/api${OrgApi.Org}`, () => { |
||||
|
return HttpResponse.json({ |
||||
|
status: 0, |
||||
|
message: "", |
||||
|
data: ORG_LIST, |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
export default [orgList]; |
||||
@ -0,0 +1,46 @@ |
|||||
|
import { faker } from "@faker-js/faker"; |
||||
|
import { http, HttpResponse, delay } from "msw"; |
||||
|
|
||||
|
import { UserApi } from "@/api/services/userService"; |
||||
|
|
||||
|
import { USER_LIST } from "../assets"; |
||||
|
|
||||
|
const signIn = http.post(`/api${UserApi.SignIn}`, async ({ request }) => { |
||||
|
const { username, password } = await request.json(); |
||||
|
|
||||
|
const user = USER_LIST.find((item) => item.username === username); |
||||
|
|
||||
|
if (!user || user.password !== password) { |
||||
|
return HttpResponse.json({ |
||||
|
status: 10001, |
||||
|
message: "Incorrect username or password.", |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
return HttpResponse.json({ |
||||
|
status: 0, |
||||
|
message: "", |
||||
|
data: { |
||||
|
user, |
||||
|
accessToken: faker.string.uuid(), |
||||
|
refreshToken: faker.string.uuid(), |
||||
|
}, |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
const userList = http.get("/api/user", async () => { |
||||
|
await delay(1000); |
||||
|
return HttpResponse.json( |
||||
|
Array.from({ length: 10 }).map(() => ({ |
||||
|
fullname: faker.person.fullName(), |
||||
|
email: faker.internet.email(), |
||||
|
avatar: faker.image.avatarGitHub(), |
||||
|
address: faker.location.streetAddress(), |
||||
|
})), |
||||
|
{ |
||||
|
status: 200, |
||||
|
}, |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
export default [signIn, userList]; |
||||
@ -0,0 +1,10 @@ |
|||||
|
import { setupWorker } from "msw/browser"; |
||||
|
|
||||
|
import demoMockApi from "./handlers/_demo"; |
||||
|
import orgMockApi from "./handlers/_org"; |
||||
|
import userMockApi from "./handlers/_user"; |
||||
|
|
||||
|
const handlers = [...userMockApi, ...orgMockApi, ...demoMockApi]; |
||||
|
const worker = setupWorker(...handlers); |
||||
|
|
||||
|
export default worker; |
||||
@ -0,0 +1,9 @@ |
|||||
|
import { faker } from "@faker-js/faker"; |
||||
|
|
||||
|
export const fakeAvatars = (count) => { |
||||
|
const result = []; |
||||
|
for (let index = 0; index < count; index += 1) { |
||||
|
result.push(faker.image.avatarGitHub()); |
||||
|
} |
||||
|
return result; |
||||
|
}; |
||||
@ -0,0 +1,26 @@ |
|||||
|
import type { ApplicationConfigurationDto, ApplicationLocalizationDto } from "#/abp-core"; |
||||
|
import requestClient from "../request"; |
||||
|
|
||||
|
/** |
||||
|
* 获取应用程序配置信息 |
||||
|
*/ |
||||
|
export function getConfigApi(options?: { |
||||
|
includeLocalizationResources?: boolean; |
||||
|
}): Promise<ApplicationConfigurationDto> { |
||||
|
return requestClient.get<ApplicationConfigurationDto>("/api/abp/application-configuration", { |
||||
|
params: options, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取应用程序语言 |
||||
|
* @returns 本地化配置 |
||||
|
*/ |
||||
|
export function getLocalizationApi(options: { |
||||
|
cultureName: string; |
||||
|
onlyDynamics?: boolean; |
||||
|
}): Promise<ApplicationLocalizationDto> { |
||||
|
return requestClient.get<ApplicationLocalizationDto>("/api/abp/application-localization", { |
||||
|
params: options, |
||||
|
}); |
||||
|
} |
||||
@ -0,0 +1,2 @@ |
|||||
|
export * from "./abp"; |
||||
|
// export * from './menu';
|
||||
@ -0,0 +1,9 @@ |
|||||
|
// import type { RouteRecordStringComponent } from '@vben/types';
|
||||
|
// import requestClient from '../request';
|
||||
|
|
||||
|
/** |
||||
|
* 获取用户所有菜单 |
||||
|
*/ |
||||
|
// export async function getAllMenusApi() {
|
||||
|
// return requestClient.get<RouteRecordStringComponent[]>('/menu/all');
|
||||
|
// }
|
||||
@ -0,0 +1,28 @@ |
|||||
|
import type { ListResultDto } from "#/abp-core"; |
||||
|
import type { |
||||
|
GetTwoFactorProvidersInput, |
||||
|
TwoFactorProvider, |
||||
|
SendEmailSigninCodeDto, |
||||
|
SendPhoneSigninCodeDto, |
||||
|
} from "#/account/account"; |
||||
|
import requestClient from "@/api/request"; |
||||
|
|
||||
|
/** |
||||
|
* Get available two-factor authentication providers |
||||
|
*/ |
||||
|
export const getTwoFactorProvidersApi = (input: GetTwoFactorProvidersInput) => |
||||
|
requestClient.get<ListResultDto<TwoFactorProvider>>("/api/account/two-factor-providers", { |
||||
|
params: input, |
||||
|
}); |
||||
|
|
||||
|
/** |
||||
|
* Send sign-in verification email |
||||
|
*/ |
||||
|
export const sendEmailSigninCodeApi = (input: SendEmailSigninCodeDto) => |
||||
|
requestClient.post("/api/account/email/send-signin-code", input); |
||||
|
|
||||
|
/** |
||||
|
* Send sign-in verification SMS |
||||
|
*/ |
||||
|
export const sendPhoneSigninCodeApi = (input: SendPhoneSigninCodeDto) => |
||||
|
requestClient.post("/api/account/phone/send-signin-code", input); |
||||
@ -0,0 +1,4 @@ |
|||||
|
export * from "./token"; |
||||
|
export * from "./user"; |
||||
|
export * from "./my-session"; |
||||
|
export * from "./account"; |
||||
@ -0,0 +1,23 @@ |
|||||
|
import type { IdentitySessionDto } from "#/management/identity/sessions"; |
||||
|
import type { PagedResultDto } from "#/abp-core"; |
||||
|
import requestClient from "@/api/request"; |
||||
|
|
||||
|
export interface GetMySessionsInput { |
||||
|
filter?: string; |
||||
|
maxResultCount?: number; |
||||
|
skipCount?: number; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get current user's sessions |
||||
|
*/ |
||||
|
export const getSessionsApi = (input?: GetMySessionsInput) => |
||||
|
requestClient.get<PagedResultDto<IdentitySessionDto>>("/api/account/my-profile/sessions", { |
||||
|
params: input, |
||||
|
}); |
||||
|
|
||||
|
/** |
||||
|
* Revoke a session |
||||
|
*/ |
||||
|
export const revokeSessionApi = (sessionId: string) => |
||||
|
requestClient.delete(`/api/account/my-profile/sessions/${sessionId}/revoke`); |
||||
@ -0,0 +1,68 @@ |
|||||
|
import type { |
||||
|
ProfileDto, |
||||
|
UpdateProfileDto, |
||||
|
ChangePasswordInput, |
||||
|
TwoFactorEnabledDto, |
||||
|
AuthenticatorDto, |
||||
|
VerifyAuthenticatorCodeInput, |
||||
|
AuthenticatorRecoveryCodeDto, |
||||
|
SendEmailConfirmCodeDto, |
||||
|
ConfirmEmailInput, |
||||
|
} from "#/account/profile"; |
||||
|
import requestClient from "@/api/request"; |
||||
|
|
||||
|
/** |
||||
|
* Get profile information |
||||
|
*/ |
||||
|
export const getApi = () => requestClient.get<ProfileDto>("/api/account/my-profile"); |
||||
|
|
||||
|
/** |
||||
|
* Update profile information |
||||
|
*/ |
||||
|
export const updateApi = (input: UpdateProfileDto) => requestClient.put<ProfileDto>("/api/account/my-profile", input); |
||||
|
|
||||
|
/** |
||||
|
* Change password |
||||
|
*/ |
||||
|
export const changePasswordApi = (input: ChangePasswordInput) => |
||||
|
requestClient.post("/api/account/my-profile/change-password", input); |
||||
|
|
||||
|
/** |
||||
|
* Get two-factor authentication status |
||||
|
*/ |
||||
|
export const getTwoFactorEnabledApi = () => |
||||
|
requestClient.get<TwoFactorEnabledDto>("/api/account/my-profile/two-factor"); |
||||
|
|
||||
|
/** |
||||
|
* Set two-factor authentication status |
||||
|
*/ |
||||
|
export const changeTwoFactorEnabledApi = (input: TwoFactorEnabledDto) => |
||||
|
requestClient.put("/api/account/my-profile/change-two-factor", input); |
||||
|
|
||||
|
/** |
||||
|
* Get authenticator configuration |
||||
|
*/ |
||||
|
export const getAuthenticatorApi = () => requestClient.get<AuthenticatorDto>("/api/account/my-profile/authenticator"); |
||||
|
|
||||
|
/** |
||||
|
* Verify authenticator code |
||||
|
*/ |
||||
|
export const verifyAuthenticatorCodeApi = (input: VerifyAuthenticatorCodeInput) => |
||||
|
requestClient.post<AuthenticatorRecoveryCodeDto>("/api/account/my-profile/verify-authenticator-code", input); |
||||
|
|
||||
|
/** |
||||
|
* Reset authenticator |
||||
|
*/ |
||||
|
export const resetAuthenticatorApi = () => requestClient.post("/api/account/my-profile/reset-authenticator"); |
||||
|
|
||||
|
/** |
||||
|
* Send email confirmation link |
||||
|
*/ |
||||
|
export const sendEmailConfirmLinkApi = (input: SendEmailConfirmCodeDto) => |
||||
|
requestClient.post("/api/account/my-profile/send-email-confirm-link", input); |
||||
|
|
||||
|
/** |
||||
|
* Confirm email |
||||
|
*/ |
||||
|
export const confirmEmailApi = (input: ConfirmEmailInput) => |
||||
|
requestClient.put("/api/account/my-profile/confirm-email", input); |
||||
@ -0,0 +1,63 @@ |
|||||
|
import type { OAuthTokenResult, PasswordTokenRequestModel, RefreshTokenRequestModel, TokenResult } from "#/account"; |
||||
|
import requestClient from "../request"; |
||||
|
|
||||
|
/** |
||||
|
* 用户登录 |
||||
|
* @param request 参数 |
||||
|
* @returns 用户token |
||||
|
*/ |
||||
|
export async function loginApi(request: PasswordTokenRequestModel): Promise<TokenResult> { |
||||
|
const clientId = import.meta.env.VITE_GLOB_CLIENT_ID; |
||||
|
const clientSecret = import.meta.env.VITE_GLOB_CLIENT_SECRET; |
||||
|
const scope = import.meta.env.VITE_GLOB_SCOPE; |
||||
|
const result = await requestClient.post<OAuthTokenResult>( |
||||
|
"/connect/token", |
||||
|
{ |
||||
|
client_id: clientId, |
||||
|
client_secret: clientSecret, |
||||
|
grant_type: "password", |
||||
|
password: request.password, |
||||
|
scope: scope, |
||||
|
username: request.username, |
||||
|
}, |
||||
|
{ |
||||
|
headers: { |
||||
|
"Content-Type": "application/x-www-form-urlencoded", |
||||
|
}, |
||||
|
timeout: 30_000, |
||||
|
}, |
||||
|
); |
||||
|
return { |
||||
|
accessToken: result.access_token, |
||||
|
expiresIn: result.expires_in, |
||||
|
refreshToken: result.refresh_token, |
||||
|
tokenType: result.token_type, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export async function refreshToken(request: RefreshTokenRequestModel): Promise<TokenResult> { |
||||
|
const clientId = import.meta.env.VITE_GLOB_CLIENT_ID; |
||||
|
const clientSecret = import.meta.env.VITE_GLOB_CLIENT_SECRET; |
||||
|
const scope = import.meta.env.VITE_GLOB_SCOPE; |
||||
|
const result = await requestClient.post<OAuthTokenResult>( |
||||
|
"/connect/token", |
||||
|
{ |
||||
|
client_id: clientId, |
||||
|
client_secret: clientSecret, |
||||
|
grant_type: "refresh_token", |
||||
|
refresh_token: request.refreshToken, |
||||
|
scope: scope, |
||||
|
}, |
||||
|
{ |
||||
|
headers: { |
||||
|
"Content-Type": "application/x-www-form-urlencoded", |
||||
|
}, |
||||
|
}, |
||||
|
); |
||||
|
return { |
||||
|
accessToken: result.access_token, |
||||
|
expiresIn: result.expires_in, |
||||
|
refreshToken: result.refresh_token, |
||||
|
tokenType: result.token_type, |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
import type { OAuthUserInfo, UserInfo } from "#/account"; |
||||
|
import requestClient from "../request"; |
||||
|
|
||||
|
/** |
||||
|
* 获取用户信息 |
||||
|
*/ |
||||
|
export async function getUserInfoApi(): Promise<UserInfo> { |
||||
|
const result = await requestClient.get<OAuthUserInfo>("/connect/userinfo"); |
||||
|
return { |
||||
|
...result, |
||||
|
emailVerified: result.email_verified, |
||||
|
givenName: result.given_name, |
||||
|
phoneNumberVerified: result.phone_number_verified, |
||||
|
preferredUsername: result.preferred_username, |
||||
|
uniqueName: result.unique_name, |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,98 @@ |
|||||
|
import axios, { type AxiosRequestConfig, type AxiosError, type AxiosResponse } from "axios"; |
||||
|
|
||||
|
import { t } from "@/locales/i18n"; |
||||
|
import userStore, { useUserToken } from "@/store/userStore"; |
||||
|
|
||||
|
import { toast } from "sonner"; |
||||
|
//TODO rm
|
||||
|
// 创建 axios 实例
|
||||
|
const axiosInstance = axios.create({ |
||||
|
baseURL: import.meta.env.VITE_APP_BASE_API, |
||||
|
timeout: 50000, |
||||
|
headers: { "Content-Type": "application/json;charset=utf-8" }, |
||||
|
}); |
||||
|
|
||||
|
// 请求拦截
|
||||
|
axiosInstance.interceptors.request.use( |
||||
|
(config) => { |
||||
|
// 在请求被发送之前做些什么
|
||||
|
const { accessToken } = useUserToken(); |
||||
|
config.headers.Authorization = `${accessToken}`; |
||||
|
return config; |
||||
|
}, |
||||
|
(error) => { |
||||
|
// 请求错误时做些什么
|
||||
|
return Promise.reject(error); |
||||
|
}, |
||||
|
); |
||||
|
|
||||
|
// 响应拦截
|
||||
|
axiosInstance.interceptors.response.use( |
||||
|
(res: AxiosResponse<any>) => { |
||||
|
const { data, status, headers } = res; |
||||
|
|
||||
|
if (headers._abpwrapresult === "true") { |
||||
|
const { code, result, message, details } = data; |
||||
|
const hasSuccess = data && Reflect.has(data, "code") && code === "0"; |
||||
|
if (hasSuccess) { |
||||
|
return result; |
||||
|
} |
||||
|
const content = details || message; |
||||
|
|
||||
|
throw new Error(content); |
||||
|
} |
||||
|
|
||||
|
if (status >= 200 && status < 400) { |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
// 业务请求错误
|
||||
|
throw new Error(t("sys.api.apiRequestFailed")); |
||||
|
}, |
||||
|
(error: AxiosError<any>) => { |
||||
|
const { response, message } = error || {}; |
||||
|
|
||||
|
const errMsg = response?.data?.message || message || t("sys.api.errorMessage"); |
||||
|
toast.error(errMsg, { |
||||
|
position: "top-center", |
||||
|
}); |
||||
|
|
||||
|
const status = response?.status; |
||||
|
if (status === 401) { |
||||
|
userStore.getState().actions.clearUserInfoAndToken(); |
||||
|
} |
||||
|
return Promise.reject(error); |
||||
|
}, |
||||
|
); |
||||
|
|
||||
|
class APIClient { |
||||
|
get<T = any>(config: AxiosRequestConfig): Promise<T> { |
||||
|
return this.request({ ...config, method: "GET" }); |
||||
|
} |
||||
|
|
||||
|
post<T = any>(config: AxiosRequestConfig): Promise<T> { |
||||
|
return this.request({ ...config, method: "POST" }); |
||||
|
} |
||||
|
|
||||
|
put<T = any>(config: AxiosRequestConfig): Promise<T> { |
||||
|
return this.request({ ...config, method: "PUT" }); |
||||
|
} |
||||
|
|
||||
|
delete<T = any>(config: AxiosRequestConfig): Promise<T> { |
||||
|
return this.request({ ...config, method: "DELETE" }); |
||||
|
} |
||||
|
|
||||
|
request<T = any>(config: AxiosRequestConfig): Promise<T> { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
axiosInstance |
||||
|
.request<any, AxiosResponse<any>>(config) |
||||
|
.then((res: AxiosResponse<any>) => { |
||||
|
resolve(res as unknown as Promise<T>); |
||||
|
}) |
||||
|
.catch((e: Error | AxiosError) => { |
||||
|
reject(e); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
export default new APIClient(); |
||||
@ -0,0 +1,3 @@ |
|||||
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
export * from "./sdk.gen"; |
||||
|
export * from "./types.gen"; |
||||
@ -0,0 +1,30 @@ |
|||||
|
import type { PagedResultDto } from "#/abp-core"; |
||||
|
|
||||
|
import type { AuditLogDto, AuditLogGetListInput } from "#/management/auditing"; |
||||
|
import requestClient from "../../request"; |
||||
|
|
||||
|
/** |
||||
|
* 获取审计日志 |
||||
|
* @param id 日志id |
||||
|
*/ |
||||
|
export function getApi(id: string): Promise<AuditLogDto> { |
||||
|
return requestClient.get<AuditLogDto>(`/api/auditing/audit-log/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取审计日志分页列表 |
||||
|
* @param input 参数 |
||||
|
*/ |
||||
|
export function getPagedListApi(input: AuditLogGetListInput): Promise<PagedResultDto<AuditLogDto>> { |
||||
|
return requestClient.get<PagedResultDto<AuditLogDto>>("/api/auditing/audit-log", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除审计日志 |
||||
|
* @param id 日志id |
||||
|
*/ |
||||
|
export function deleteApi(id: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/auditing/audit-log/${id}`); |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
import type { ListResultDto } from "#/abp-core"; |
||||
|
|
||||
|
import type { EntityChangeGetWithUsernameInput, EntityChangeWithUsernameDto } from "#/management/auditing"; |
||||
|
import requestClient from "../../request"; |
||||
|
|
||||
|
/** |
||||
|
* 获取包含用户名称的实体变更列表 |
||||
|
* @param input 参数 |
||||
|
*/ |
||||
|
export function getListWithUsernameApi( |
||||
|
input: EntityChangeGetWithUsernameInput, |
||||
|
): Promise<ListResultDto<EntityChangeWithUsernameDto>> { |
||||
|
return requestClient.get<ListResultDto<EntityChangeWithUsernameDto>>("/api/auditing/entity-changes/with-username", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
@ -0,0 +1,2 @@ |
|||||
|
export * as auditLogsApi from "./audit-logs"; |
||||
|
export * as entityChangesApi from "./entity-changes"; |
||||
@ -0,0 +1,64 @@ |
|||||
|
import type { ListResultDto, PagedResultDto } from "#/abp-core"; |
||||
|
|
||||
|
import type { |
||||
|
GetIdentityClaimTypePagedListInput, |
||||
|
IdentityClaimTypeCreateDto, |
||||
|
IdentityClaimTypeDto, |
||||
|
IdentityClaimTypeUpdateDto, |
||||
|
} from "#/management/identity"; |
||||
|
import requestClient from "../../request"; |
||||
|
|
||||
|
/** |
||||
|
* 新增用户声明 |
||||
|
* @param input 参数 |
||||
|
* @returns 用户声明实体数据传输对象 |
||||
|
*/ |
||||
|
export function createApi(input: IdentityClaimTypeCreateDto): Promise<IdentityClaimTypeDto> { |
||||
|
return requestClient.post<IdentityClaimTypeDto>("/api/identity/claim-types", input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除用户声明 |
||||
|
* @param id 用户声明id |
||||
|
*/ |
||||
|
export function deleteApi(id: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/identity/claim-types/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询用户声明 |
||||
|
* @param id 用户声明id |
||||
|
* @returns 用户声明实体数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(id: string): Promise<IdentityClaimTypeDto> { |
||||
|
return requestClient.get<IdentityClaimTypeDto>(`/api/identity/claim-types/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新用户声明 |
||||
|
* @param id 用户声明id |
||||
|
* @returns 用户声明实体数据传输对象 |
||||
|
*/ |
||||
|
export function updateApi(id: string, input: IdentityClaimTypeUpdateDto): Promise<IdentityClaimTypeDto> { |
||||
|
return requestClient.put<IdentityClaimTypeDto>(`/api/identity/claim-types/${id}`, input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询用户声明分页列表 |
||||
|
* @param input 过滤参数 |
||||
|
* @returns 用户声明实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getPagedListApi( |
||||
|
input?: GetIdentityClaimTypePagedListInput, |
||||
|
): Promise<PagedResultDto<IdentityClaimTypeDto>> { |
||||
|
return requestClient.get<PagedResultDto<IdentityClaimTypeDto>>("/api/identity/claim-types", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取可用的声明类型列表 |
||||
|
*/ |
||||
|
export function getAssignableClaimsApi(): Promise<ListResultDto<IdentityClaimTypeDto>> { |
||||
|
return requestClient.get<ListResultDto<IdentityClaimTypeDto>>("/api/identity/claim-types/actived-list"); |
||||
|
} |
||||
@ -0,0 +1,173 @@ |
|||||
|
import type { ListResultDto, PagedResultDto } from "#/abp-core"; |
||||
|
|
||||
|
import type { IdentityRoleDto, IdentityUserDto } from "#/management/identity"; |
||||
|
import type { |
||||
|
GetIdentityRolesInput, |
||||
|
GetIdentityUsersInput, |
||||
|
GetOrganizationUnitPagedListInput, |
||||
|
GetUnaddedRoleListInput, |
||||
|
GetUnaddedUserListInput, |
||||
|
OrganizationUnitAddRoleDto, |
||||
|
OrganizationUnitAddUserDto, |
||||
|
OrganizationUnitCreateDto, |
||||
|
OrganizationUnitDto, |
||||
|
OrganizationUnitGetChildrenDto, |
||||
|
OrganizationUnitUpdateDto, |
||||
|
} from "#/management/identity/organization-units"; |
||||
|
|
||||
|
import requestClient from "../../request"; |
||||
|
|
||||
|
/** |
||||
|
* 新增组织机构 |
||||
|
* @param input 参数 |
||||
|
* @returns 组织机构实体数据传输对象 |
||||
|
*/ |
||||
|
export function createApi(input: OrganizationUnitCreateDto): Promise<OrganizationUnitDto> { |
||||
|
return requestClient.post<OrganizationUnitDto>("/api/identity/organization-units", input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除组织机构 |
||||
|
* @param id 组织机构id |
||||
|
*/ |
||||
|
export function deleteApi(id: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/identity/organization-units/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询组织机构 |
||||
|
* @param id 组织机构id |
||||
|
* @returns 组织机构实体数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(id: string): Promise<OrganizationUnitDto> { |
||||
|
return requestClient.get<OrganizationUnitDto>(`/api/identity/organization-units/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新组织机构 |
||||
|
* @param id 组织机构id |
||||
|
* @returns 组织机构实体数据传输对象 |
||||
|
*/ |
||||
|
|
||||
|
export function updateApi(id: string, input: OrganizationUnitUpdateDto): Promise<OrganizationUnitDto> { |
||||
|
return requestClient.put<OrganizationUnitDto>(`/api/identity/organization-units/${id}`, input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询组织机构分页列表 |
||||
|
* @param input 过滤参数 |
||||
|
* @returns 组织机构实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getPagedListApi( |
||||
|
input?: GetOrganizationUnitPagedListInput, |
||||
|
): Promise<PagedResultDto<OrganizationUnitDto>> { |
||||
|
return requestClient.get<PagedResultDto<OrganizationUnitDto>>("/api/identity/organization-units", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询根组织机构列表 |
||||
|
* @returns 组织机构实体数据传输对象列表 |
||||
|
*/ |
||||
|
export function getRootListApi(): Promise<ListResultDto<OrganizationUnitDto>> { |
||||
|
return requestClient.get<ListResultDto<OrganizationUnitDto>>("/api/identity/organization-units/root-node"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询组织机构列表 |
||||
|
* @returns 组织机构实体数据传输对象列表 |
||||
|
*/ |
||||
|
export function getAllListApi(): Promise<ListResultDto<OrganizationUnitDto>> { |
||||
|
return requestClient.get<ListResultDto<OrganizationUnitDto>>("/api/identity/organization-units/all"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询下级组织机构列表 |
||||
|
* @param input 查询参数 |
||||
|
* @returns 组织机构实体数据传输对象列表 |
||||
|
*/ |
||||
|
export function getChildrenApi(input: OrganizationUnitGetChildrenDto): Promise<ListResultDto<OrganizationUnitDto>> { |
||||
|
return requestClient.get<ListResultDto<OrganizationUnitDto>>("/api/identity/organization-units/find-children", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询组织机构用户列表 |
||||
|
* @param id 组织机构id |
||||
|
* @param input 查询过滤参数 |
||||
|
* @returns 用户实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getUserListApi(id: string, input?: GetIdentityUsersInput): Promise<PagedResultDto<IdentityUserDto>> { |
||||
|
return requestClient.get<PagedResultDto<IdentityUserDto>>(`/api/identity/organization-units/${id}/users`, { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询未加入组织机构的用户列表 |
||||
|
* @param input 查询过滤参数 |
||||
|
* @returns 用户实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getUnaddedUserListApi(input: GetUnaddedUserListInput): Promise<PagedResultDto<IdentityUserDto>> { |
||||
|
return requestClient.get<PagedResultDto<IdentityUserDto>>( |
||||
|
`/api/identity/organization-units/${input.id}/unadded-users`, |
||||
|
{ |
||||
|
params: input, |
||||
|
}, |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 用户添加到组织机构 |
||||
|
* @param id 组织机构id |
||||
|
* @param input 用户id列表 |
||||
|
*/ |
||||
|
export function addMembers(id: string, input: OrganizationUnitAddUserDto): Promise<void> { |
||||
|
return requestClient.post(`/api/identity/organization-units/${id}/users`, input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询组织机构角色列表 |
||||
|
* @param id 组织机构id |
||||
|
* @param input 查询过滤参数 |
||||
|
* @returns 角色实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getRoleListApi(id: string, input?: GetIdentityRolesInput): Promise<PagedResultDto<IdentityRoleDto>> { |
||||
|
return requestClient.get<PagedResultDto<IdentityRoleDto>>(`/api/identity/organization-units/${id}/roles`, { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询未加入组织机构的角色列表 |
||||
|
* @param input 查询过滤参数 |
||||
|
* @returns 角色实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getUnaddedRoleListApi(input: GetUnaddedRoleListInput): Promise<PagedResultDto<IdentityRoleDto>> { |
||||
|
return requestClient.get<PagedResultDto<IdentityRoleDto>>( |
||||
|
`/api/identity/organization-units/${input.id}/unadded-roles`, |
||||
|
{ |
||||
|
params: input, |
||||
|
}, |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 角色添加到组织机构 |
||||
|
* @param id 组织机构id |
||||
|
* @param input 角色id列表 |
||||
|
*/ |
||||
|
export function addRoles(id: string, input: OrganizationUnitAddRoleDto): Promise<void> { |
||||
|
return requestClient.post(`/api/identity/organization-units/${id}/roles`, input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 移动组织机构 |
||||
|
* @param id 组织机构id |
||||
|
* @param parentId 父级组织机构id |
||||
|
*/ |
||||
|
export function moveTo(id: string, parentId?: string): Promise<void> { |
||||
|
return requestClient.put(`api/identity/organization-units/${id}/move`, { parentId }); |
||||
|
} |
||||
@ -0,0 +1,109 @@ |
|||||
|
import type { PagedResultDto, ListResultDto } from "#/abp-core"; |
||||
|
|
||||
|
import type { |
||||
|
IdentityClaimCreateDto, |
||||
|
IdentityClaimDeleteDto, |
||||
|
IdentityClaimDto, |
||||
|
IdentityClaimUpdateDto, |
||||
|
} from "#/management/identity/claims"; |
||||
|
|
||||
|
import type { |
||||
|
GetRolePagedListInput, |
||||
|
IdentityRoleCreateDto, |
||||
|
IdentityRoleDto, |
||||
|
IdentityRoleUpdateDto, |
||||
|
} from "#/management/identity"; |
||||
|
|
||||
|
import requestClient from "../../request"; |
||||
|
|
||||
|
/** |
||||
|
* 新增角色 |
||||
|
* @param input 参数 |
||||
|
* @returns 角色实体数据传输对象 |
||||
|
*/ |
||||
|
export function createApi(input: IdentityRoleCreateDto): Promise<IdentityRoleDto> { |
||||
|
return requestClient.post<IdentityRoleDto>("/api/identity/roles", input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除角色 |
||||
|
* @param id 角色id |
||||
|
*/ |
||||
|
export function deleteApi(id: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/identity/roles/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询角色 |
||||
|
* @param id 角色id |
||||
|
* @returns 角色实体数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(id: string): Promise<IdentityRoleDto> { |
||||
|
return requestClient.get<IdentityRoleDto>(`/api/identity/roles/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新角色 |
||||
|
* @param id 角色id |
||||
|
* @returns 角色实体数据传输对象 |
||||
|
*/ |
||||
|
export function updateApi(id: string, input: IdentityRoleUpdateDto): Promise<IdentityRoleDto> { |
||||
|
return requestClient.put<IdentityRoleDto>(`/api/identity/roles/${id}`, input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询角色分页列表 |
||||
|
* @param input 过滤参数 |
||||
|
* @returns 角色实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getPagedListApi(input?: GetRolePagedListInput): Promise<PagedResultDto<IdentityRoleDto>> { |
||||
|
return requestClient.get<PagedResultDto<IdentityRoleDto>>("/api/identity/roles", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 从组织机构中移除角色 |
||||
|
* @param id 角色id |
||||
|
* @param ouId 组织机构id |
||||
|
*/ |
||||
|
export function removeOrganizationUnitApi(id: string, ouId: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/identity/roles/${id}/organization-units/${ouId}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取角色声明列表 |
||||
|
* @param id 角色id |
||||
|
*/ |
||||
|
export function getClaimsApi(id: string): Promise<ListResultDto<IdentityClaimDto>> { |
||||
|
return requestClient.get<ListResultDto<IdentityClaimDto>>(`/api/identity/roles/${id}/claims`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除角色声明 |
||||
|
* @param id 角色id |
||||
|
* @param input 角色声明dto |
||||
|
*/ |
||||
|
export function deleteClaimApi(id: string, input: IdentityClaimDeleteDto): Promise<void> { |
||||
|
return requestClient.delete(`/api/identity/roles/${id}/claims`, { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 创建角色声明 |
||||
|
* @param id 角色id |
||||
|
* @param input 角色声明dto |
||||
|
*/ |
||||
|
export function createClaimApi(id: string, input: IdentityClaimCreateDto): Promise<void> { |
||||
|
return requestClient.post(`/api/identity/roles/${id}/claims`, input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新角色声明 |
||||
|
* @param id 角色id |
||||
|
* @param input 用户角色dto |
||||
|
*/ |
||||
|
export function updateClaimApi(id: string, input: IdentityClaimUpdateDto): Promise<void> { |
||||
|
return requestClient.put(`/api/identity/roles/${id}/claims`, input); |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
import type { GetSecurityLogPagedRequest, SecurityLogDto } from "#/management/identity"; |
||||
|
import type { PagedResultDto } from "#/abp-core"; |
||||
|
import requestClient from "../../request"; |
||||
|
|
||||
|
/** |
||||
|
* 删除安全日志 |
||||
|
* @param id 安全日志id |
||||
|
*/ |
||||
|
export function deleteApi(id: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/auditing/security-log/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询安全日志 |
||||
|
* @param id 安全日志id |
||||
|
* @returns 安全日志实体数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(id: string): Promise<SecurityLogDto> { |
||||
|
return requestClient.get<SecurityLogDto>(`/api/auditing/security-log/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询安全日志分页列表 |
||||
|
* @param input 过滤参数 |
||||
|
* @returns 安全日志实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getPagedListApi(input?: GetSecurityLogPagedRequest): Promise<PagedResultDto<SecurityLogDto>> { |
||||
|
return requestClient.get<PagedResultDto<SecurityLogDto>>("/api/auditing/security-log", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
import type { ListResultDto } from "#/abp-core"; |
||||
|
|
||||
|
import type { IdentityUserDto, UserLookupCountInput, UserLookupSearchInput } from "#/management/identity/user"; |
||||
|
|
||||
|
import requestClient from "../../request"; |
||||
|
|
||||
|
/** |
||||
|
* 通过id查询用户 |
||||
|
* @param id 用户id |
||||
|
* @returns 用户实体数据传输对象 |
||||
|
*/ |
||||
|
export function findByIdApi(id: string): Promise<IdentityUserDto> { |
||||
|
return requestClient.get<IdentityUserDto>(`/api/identity/users/lookup/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 通过用户名查询用户 |
||||
|
* @param userName 用户名 |
||||
|
* @returns 用户实体数据传输对象 |
||||
|
*/ |
||||
|
export function findByUserNameApi(userName: string): Promise<IdentityUserDto> { |
||||
|
return requestClient.get<IdentityUserDto>(`/api/identity/users/lookup/by-username/${userName}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 搜索用户列表 |
||||
|
* @param input 搜索过滤条件 |
||||
|
* @returns 用户实体数据传输对象列表 |
||||
|
*/ |
||||
|
export function searchApi(input?: UserLookupSearchInput): Promise<ListResultDto<IdentityUserDto>> { |
||||
|
return requestClient.get<ListResultDto<IdentityUserDto>>("/api/identity/users/lookup/search", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 搜索用户数量 |
||||
|
* @param input 搜索过滤条件 |
||||
|
*/ |
||||
|
export function countApi(input?: UserLookupCountInput): Promise<number> { |
||||
|
return requestClient.get<number>("/api/identity/users/lookup/count", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
import type { PagedResultDto } from "#/abp-core"; |
||||
|
import type { GetUserSessionsInput, IdentitySessionDto } from "#/management/identity/sessions"; |
||||
|
import requestClient from "@/api/request"; |
||||
|
|
||||
|
/** |
||||
|
* 查询会话列表 |
||||
|
* @param { GetUserSessionsInput } input 查询参数 |
||||
|
* @returns { Promise<PagedResultDto<IdentitySessionDto>> } 用户会话列表 |
||||
|
*/ |
||||
|
export function getSessionsApi(input?: GetUserSessionsInput): Promise<PagedResultDto<IdentitySessionDto>> { |
||||
|
return requestClient.get<PagedResultDto<IdentitySessionDto>>("/api/identity/sessions", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
/** |
||||
|
* 撤销会话 |
||||
|
* @param { string } sessionId 会话id |
||||
|
* @returns { Promise<void> } |
||||
|
*/ |
||||
|
export function revokeSessionApi(sessionId: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/identity/sessions/${sessionId}/revoke`); |
||||
|
} |
||||
@ -0,0 +1,155 @@ |
|||||
|
import type { ListResultDto, PagedResultDto } from "#/abp-core"; |
||||
|
import type { IdentityRoleDto, OrganizationUnitDto } from "#/management/identity"; |
||||
|
import type { |
||||
|
IdentityClaimCreateDto, |
||||
|
IdentityClaimDeleteDto, |
||||
|
IdentityClaimDto, |
||||
|
IdentityClaimUpdateDto, |
||||
|
} from "#/management/identity/claims"; |
||||
|
import type { |
||||
|
ChangeUserPasswordInput, |
||||
|
GetUserPagedListInput, |
||||
|
IdentityUserCreateDto, |
||||
|
IdentityUserDto, |
||||
|
IdentityUserUpdateDto, |
||||
|
} from "#/management/identity"; |
||||
|
import requestClient from "../../request"; |
||||
|
|
||||
|
/** |
||||
|
* 新增用户 |
||||
|
* @param input 参数 |
||||
|
* @returns 用户实体数据传输对象 |
||||
|
*/ |
||||
|
export function createApi(input: IdentityUserCreateDto): Promise<IdentityUserDto> { |
||||
|
return requestClient.post<IdentityUserDto>("/api/identity/users", input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除用户 |
||||
|
* @param id 用户id |
||||
|
*/ |
||||
|
export function deleteApi(id: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/identity/users/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询用户 |
||||
|
* @param id 用户id |
||||
|
* @returns 用户实体数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(id: string): Promise<IdentityUserDto> { |
||||
|
return requestClient.get<IdentityUserDto>(`/api/identity/users/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新用户 |
||||
|
* @param id 用户id |
||||
|
* @returns 用户实体数据传输对象 |
||||
|
*/ |
||||
|
export function updateApi(id: string, input: IdentityUserUpdateDto): Promise<IdentityUserDto> { |
||||
|
return requestClient.put<IdentityUserDto>(`/api/identity/users/${id}`, input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询用户分页列表 |
||||
|
* @param input 过滤参数 |
||||
|
* @returns 用户实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getPagedListApi(input?: GetUserPagedListInput): Promise<PagedResultDto<IdentityUserDto>> { |
||||
|
return requestClient.get<PagedResultDto<IdentityUserDto>>("/api/identity/users", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 从组织机构中移除用户 |
||||
|
* @param id 用户id |
||||
|
* @param ouId 组织机构id |
||||
|
*/ |
||||
|
export function removeOrganizationUnitApi(id: string, ouId: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/identity/users/${id}/organization-units/${ouId}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取用户组织机构列表 |
||||
|
* @param id 用户id |
||||
|
*/ |
||||
|
export function getOrganizationUnitsApi(id: string): Promise<ListResultDto<OrganizationUnitDto>> { |
||||
|
return requestClient.get<ListResultDto<OrganizationUnitDto>>(`/api/identity/users/${id}/organization-units`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 锁定用户 |
||||
|
* @param id 用户id |
||||
|
* @param seconds 锁定时长(秒) |
||||
|
*/ |
||||
|
export function lockApi(id: string, seconds: number): Promise<void> { |
||||
|
return requestClient.put(`/api/identity/users/${id}/lock/${seconds}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 解锁用户 |
||||
|
* @param id 用户id |
||||
|
*/ |
||||
|
export function unLockApi(id: string): Promise<void> { |
||||
|
return requestClient.put(`/api/identity/users/${id}/unlock`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更改用户密码 |
||||
|
* @param id 用户id |
||||
|
* @param input 密码变更dto |
||||
|
*/ |
||||
|
export function changePasswordApi(id: string, input: ChangeUserPasswordInput): Promise<void> { |
||||
|
return requestClient.put(`/api/identity/users/change-password?id=${id}`, input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取可用的角色列表 |
||||
|
*/ |
||||
|
export function getAssignableRolesApi(): Promise<ListResultDto<IdentityRoleDto>> { |
||||
|
return requestClient.get<ListResultDto<IdentityRoleDto>>("/api/identity/users/assignable-roles"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取用户角色列表 |
||||
|
* @param id 用户id |
||||
|
*/ |
||||
|
export function getRolesApi(id: string): Promise<ListResultDto<IdentityRoleDto>> { |
||||
|
return requestClient.get<ListResultDto<IdentityRoleDto>>(`/api/identity/users/${id}/roles`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取用户声明列表 |
||||
|
* @param id 用户id |
||||
|
*/ |
||||
|
export function getClaimsApi(id: string): Promise<ListResultDto<IdentityClaimDto>> { |
||||
|
return requestClient.get<ListResultDto<IdentityClaimDto>>(`/api/identity/users/${id}/claims`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除用户声明 |
||||
|
* @param id 用户id |
||||
|
* @param input 用户声明dto |
||||
|
*/ |
||||
|
export function deleteClaimApi(id: string, input: IdentityClaimDeleteDto): Promise<void> { |
||||
|
return requestClient.delete(`/api/identity/users/${id}/claims`, { params: input }); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 创建用户声明 |
||||
|
* @param id 用户id |
||||
|
* @param input 用户声明dto |
||||
|
*/ |
||||
|
export function createClaimApi(id: string, input: IdentityClaimCreateDto): Promise<void> { |
||||
|
return requestClient.post(`/api/identity/users/${id}/claims`, input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新用户声明 |
||||
|
* @param id 用户id |
||||
|
* @param input 用户声明dto |
||||
|
*/ |
||||
|
export function updateClaimApi(id: string, input: IdentityClaimUpdateDto): Promise<void> { |
||||
|
return requestClient.put(`/api/identity/users/${id}/claims`, input); |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
import type { PagedResultDto } from "#/abp-core"; |
||||
|
|
||||
|
import type { |
||||
|
GetMyNotifilerPagedListInput, |
||||
|
MarkReadStateInput, |
||||
|
UserNotificationDto, |
||||
|
} from "#/notifications/my-notifilers"; |
||||
|
|
||||
|
import requestClient from "@/api/request"; |
||||
|
/** |
||||
|
* 获取我的通知列表 |
||||
|
* @param {GetMyNotifilerPagedListInput} input 参数 |
||||
|
* @returns {Promise<PagedResultDto<UserNotificationDto>>} 通知分页列表 |
||||
|
*/ |
||||
|
export function getMyNotifilersApi(input?: GetMyNotifilerPagedListInput): Promise<PagedResultDto<UserNotificationDto>> { |
||||
|
return requestClient.get<PagedResultDto<UserNotificationDto>>("/api/notifications/my-notifilers", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
/** |
||||
|
* 删除我的通知 |
||||
|
* @param {string} id 通知id |
||||
|
* @returns {void} |
||||
|
*/ |
||||
|
export function deleteMyNotifilerApi(id: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/notifications/my-notifilers/${id}`); |
||||
|
} |
||||
|
/** |
||||
|
* 设置通知已读状态 |
||||
|
* @param {MarkReadStateInput} input 参数 |
||||
|
* @returns {void} |
||||
|
*/ |
||||
|
export function markReadStateApi(input: MarkReadStateInput): Promise<void> { |
||||
|
return requestClient.put("/api/notifications/my-notifilers/mark-read-state", input); |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
import type { ListResultDto } from "#/abp-core"; |
||||
|
|
||||
|
import type { NotificationGroupDto, NotificationTemplateDto } from "#/notifications/definitions"; |
||||
|
import type { NotificationSendInput, NotificationTemplateSendInput } from "#/notifications/notifications"; |
||||
|
|
||||
|
import requestClient from "@/api/request"; |
||||
|
|
||||
|
/** |
||||
|
* 获取可用通知列表 |
||||
|
* @returns {Promise<ListResultDto<NotificationGroupDto>>} 可用通知列表 |
||||
|
*/ |
||||
|
export function getAssignableNotifiersApi(): Promise<ListResultDto<NotificationGroupDto>> { |
||||
|
return requestClient.get<ListResultDto<NotificationGroupDto>>("/api/notifications/assignables"); |
||||
|
} |
||||
|
/** |
||||
|
* 获取可用通知模板列表 |
||||
|
* @returns {Promise<ListResultDto<NotificationTemplateDto>>} 可用通知模板列表 |
||||
|
*/ |
||||
|
export function getAssignableTemplatesApi(): Promise<ListResultDto<NotificationTemplateDto>> { |
||||
|
return requestClient.get<ListResultDto<NotificationTemplateDto>>("/api/notifications/assignable-templates", { |
||||
|
method: "GET", |
||||
|
}); |
||||
|
} |
||||
|
/** |
||||
|
* 发送通知 |
||||
|
* @param input 参数 |
||||
|
* @returns {Promise<void>} |
||||
|
*/ |
||||
|
export function sendNotiferApi(input: NotificationSendInput): Promise<void> { |
||||
|
return requestClient.post("/api/notifications/send", input); |
||||
|
} |
||||
|
/** |
||||
|
* 发送模板通知 |
||||
|
* @param input 参数 |
||||
|
* @returns {Promise<void>} |
||||
|
*/ |
||||
|
export function sendTemplateNotiferApi(input: NotificationTemplateSendInput): Promise<void> { |
||||
|
return requestClient.post("/api/notifications/send/template", input); |
||||
|
} |
||||
@ -0,0 +1,57 @@ |
|||||
|
import type { ListResultDto } from "#/abp-core"; |
||||
|
|
||||
|
import type { |
||||
|
PermissionDefinitionCreateDto, |
||||
|
PermissionDefinitionDto, |
||||
|
PermissionDefinitionGetListInput, |
||||
|
PermissionDefinitionUpdateDto, |
||||
|
} from "#/management/permissions/definitions"; |
||||
|
|
||||
|
import requestClient from "../../request"; |
||||
|
|
||||
|
/** |
||||
|
* 删除权限定义 |
||||
|
* @param name 权限名称 |
||||
|
*/ |
||||
|
export function deleteApi(name: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/permission-management/definitions/${name}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询权限定义 |
||||
|
* @param name 权限名称 |
||||
|
* @returns 权限定义数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(name: string): Promise<PermissionDefinitionDto> { |
||||
|
return requestClient.get<PermissionDefinitionDto>(`/api/permission-management/definitions/${name}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询权限定义列表 |
||||
|
* @param input 权限过滤条件 |
||||
|
* @returns 权限定义数据传输对象列表 |
||||
|
*/ |
||||
|
export function getListApi(input?: PermissionDefinitionGetListInput): Promise<ListResultDto<PermissionDefinitionDto>> { |
||||
|
return requestClient.get<ListResultDto<PermissionDefinitionDto>>("/api/permission-management/definitions", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 创建权限定义 |
||||
|
* @param input 权限定义参数 |
||||
|
* @returns 权限定义数据传输对象 |
||||
|
*/ |
||||
|
export function createApi(input: PermissionDefinitionCreateDto): Promise<PermissionDefinitionDto> { |
||||
|
return requestClient.post<PermissionDefinitionDto>("/api/permission-management/definitions", input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新权限定义 |
||||
|
* @param name 权限名称 |
||||
|
* @param input 权限定义参数 |
||||
|
* @returns 权限定义数据传输对象 |
||||
|
*/ |
||||
|
export function updateApi(name: string, input: PermissionDefinitionUpdateDto): Promise<PermissionDefinitionDto> { |
||||
|
return requestClient.put<PermissionDefinitionDto>(`/api/permission-management/definitions/${name}`, input); |
||||
|
} |
||||
@ -0,0 +1,68 @@ |
|||||
|
import type { ListResultDto } from "#/abp-core"; |
||||
|
|
||||
|
import type { |
||||
|
PermissionGroupDefinitionCreateDto, |
||||
|
PermissionGroupDefinitionDto, |
||||
|
PermissionGroupDefinitionGetListInput, |
||||
|
PermissionGroupDefinitionUpdateDto, |
||||
|
} from "#/management/permissions/groups"; |
||||
|
|
||||
|
import requestClient from "../../request"; |
||||
|
|
||||
|
/** |
||||
|
* 删除权限定义 |
||||
|
* @param name 权限名称 |
||||
|
*/ |
||||
|
export function deleteApi(name: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/permission-management/definitions/groups/${name}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询权限定义 |
||||
|
* @param name 权限名称 |
||||
|
* @returns 权限定义数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(name: string): Promise<PermissionGroupDefinitionDto> { |
||||
|
return requestClient.get<PermissionGroupDefinitionDto>(`/api/permission-management/definitions/groups/${name}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询权限定义列表 |
||||
|
* @param input 权限过滤条件 |
||||
|
* @returns 权限定义数据传输对象列表 |
||||
|
*/ |
||||
|
export function getListApi( |
||||
|
input?: PermissionGroupDefinitionGetListInput, |
||||
|
): Promise<ListResultDto<PermissionGroupDefinitionDto>> { |
||||
|
return requestClient.get<ListResultDto<PermissionGroupDefinitionDto>>( |
||||
|
"/api/permission-management/definitions/groups", |
||||
|
{ |
||||
|
params: input, |
||||
|
}, |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 创建权限定义 |
||||
|
* @param input 权限定义参数 |
||||
|
* @returns 权限定义数据传输对象 |
||||
|
*/ |
||||
|
export function createApi(input: PermissionGroupDefinitionCreateDto): Promise<PermissionGroupDefinitionDto> { |
||||
|
return requestClient.post<PermissionGroupDefinitionDto>("/api/permission-management/definitions/groups", input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新权限定义 |
||||
|
* @param name 权限名称 |
||||
|
* @param input 权限定义参数 |
||||
|
* @returns 权限定义数据传输对象 |
||||
|
*/ |
||||
|
export function updateApi( |
||||
|
name: string, |
||||
|
input: PermissionGroupDefinitionUpdateDto, |
||||
|
): Promise<PermissionGroupDefinitionDto> { |
||||
|
return requestClient.put<PermissionGroupDefinitionDto>( |
||||
|
`/api/permission-management/definitions/groups/${name}`, |
||||
|
input, |
||||
|
); |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
import type { PermissionProvider, PermissionResultDto, PermissionsUpdateDto } from "#/management/permissions"; |
||||
|
|
||||
|
import requestClient from "../../request"; |
||||
|
|
||||
|
/** |
||||
|
* 查询权限 |
||||
|
* @param provider |
||||
|
* @returns 权限实体数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(provider: PermissionProvider): Promise<PermissionResultDto> { |
||||
|
return requestClient.get<PermissionResultDto>("/api/permission-management/permissions", { |
||||
|
params: provider, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新权限 |
||||
|
* @param provider |
||||
|
* @param input |
||||
|
*/ |
||||
|
export function updateApi(provider: PermissionProvider, input: PermissionsUpdateDto): Promise<void> { |
||||
|
return requestClient.put("/api/permission-management/permissions", input, { |
||||
|
params: provider, |
||||
|
}); |
||||
|
} |
||||
@ -0,0 +1,56 @@ |
|||||
|
import type { ListResultDto } from "#/abp-core"; |
||||
|
|
||||
|
import type { |
||||
|
SettingDefinitionCreateDto, |
||||
|
SettingDefinitionDto, |
||||
|
SettingDefinitionGetListInput, |
||||
|
SettingDefinitionUpdateDto, |
||||
|
} from "#/management/settings/definitions"; |
||||
|
import requestClient from "@/api/request"; |
||||
|
|
||||
|
/** |
||||
|
* 删除设置定义 |
||||
|
* @param name 设置名称 |
||||
|
*/ |
||||
|
export function deleteApi(name: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/setting-management/settings/definitions/${name}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询设置定义 |
||||
|
* @param name 设置名称 |
||||
|
* @returns 设置定义数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(name: string): Promise<SettingDefinitionDto> { |
||||
|
return requestClient.get<SettingDefinitionDto>(`/api/setting-management/settings/definitions/${name}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询设置定义列表 |
||||
|
* @param input 设置过滤条件 |
||||
|
* @returns 设置定义数据传输对象列表 |
||||
|
*/ |
||||
|
export function getListApi(input?: SettingDefinitionGetListInput): Promise<ListResultDto<SettingDefinitionDto>> { |
||||
|
return requestClient.get<ListResultDto<SettingDefinitionDto>>("/api/setting-management/settings/definitions", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 创建设置定义 |
||||
|
* @param input 设置定义参数 |
||||
|
* @returns 设置定义数据传输对象 |
||||
|
*/ |
||||
|
export function createApi(input: SettingDefinitionCreateDto): Promise<SettingDefinitionDto> { |
||||
|
return requestClient.post<SettingDefinitionDto>("/api/setting-management/settings/definitions", input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新设置定义 |
||||
|
* @param name 设置名称 |
||||
|
* @param input 设置定义参数 |
||||
|
* @returns 设置定义数据传输对象 |
||||
|
*/ |
||||
|
export function updateApi(name: string, input: SettingDefinitionUpdateDto): Promise<SettingDefinitionDto> { |
||||
|
return requestClient.put<SettingDefinitionDto>(`/api/setting-management/settings/definitions/${name}`, input); |
||||
|
} |
||||
@ -0,0 +1,62 @@ |
|||||
|
import type { ListResultDto } from "#/abp-core"; |
||||
|
|
||||
|
import type { SettingGroup, SettingsUpdateInput } from "#/management/settings"; |
||||
|
|
||||
|
import requestClient from "@/api/request"; |
||||
|
|
||||
|
/** |
||||
|
* 获取全局设置 |
||||
|
* @returns 设置数据传输对象列表 |
||||
|
*/ |
||||
|
export function getGlobalSettingsApi(): Promise<ListResultDto<SettingGroup>> { |
||||
|
return requestClient.get<ListResultDto<SettingGroup>>("/api/setting-management/settings/by-global"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 设置全局设置 |
||||
|
* @returns 设置数据传输对象列表 |
||||
|
*/ |
||||
|
export function setGlobalSettingsApi(input: SettingsUpdateInput): Promise<void> { |
||||
|
return requestClient.put("/api/setting-management/settings/change-global", input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取租户设置 |
||||
|
* @returns 设置数据传输对象列表 |
||||
|
*/ |
||||
|
export function getTenantSettingsApi(): Promise<ListResultDto<SettingGroup>> { |
||||
|
return requestClient.get<ListResultDto<SettingGroup>>("api/setting-management/settings/by-current-tenant"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 设置租户设置 |
||||
|
* @returns 设置数据传输对象列表 |
||||
|
*/ |
||||
|
export function setTenantSettingsApi(input: SettingsUpdateInput): Promise<void> { |
||||
|
return requestClient.put("/api/setting-management/settings/change-current-tenant", input); |
||||
|
} |
||||
|
/** |
||||
|
* 获取用户设置 |
||||
|
* @returns 设置数据传输对象列表 |
||||
|
*/ |
||||
|
export function getUserSettingsApi(): Promise<ListResultDto<SettingGroup>> { |
||||
|
return requestClient.get<ListResultDto<SettingGroup>>("/api/setting-management/settings/by-current-user"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 设置用户设置 |
||||
|
* @returns 设置数据传输对象列表 |
||||
|
*/ |
||||
|
export function setUserSettingsApi(input: SettingsUpdateInput): Promise<void> { |
||||
|
return requestClient.put("/api/setting-management/settings/change-current-user", input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 发送测试邮件 |
||||
|
* @param emailAddress 邮件接收方地址 |
||||
|
*/ |
||||
|
export const sendTestEmailApi = (emailAddress: string) => { |
||||
|
return requestClient.post("/api/setting-management/settings/send-test-email", { |
||||
|
emailAddress, |
||||
|
}); |
||||
|
}; |
||||
@ -0,0 +1,58 @@ |
|||||
|
import type { PagedResultDto } from "#/abp-core"; |
||||
|
import type { |
||||
|
OpenIddictApplicationCreateDto, |
||||
|
OpenIddictApplicationDto, |
||||
|
OpenIddictApplicationGetListInput, |
||||
|
OpenIddictApplicationUpdateDto, |
||||
|
} from "#/openiddict/applications"; |
||||
|
|
||||
|
import requestClient from "../request"; |
||||
|
|
||||
|
/** |
||||
|
* 创建应用 |
||||
|
* @param input 参数 |
||||
|
* @returns 应用实体数据传输对象 |
||||
|
*/ |
||||
|
export function createApi(input: OpenIddictApplicationCreateDto): Promise<OpenIddictApplicationDto> { |
||||
|
return requestClient.post<OpenIddictApplicationDto>("/api/openiddict/applications", input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除应用 |
||||
|
* @param id 应用id |
||||
|
*/ |
||||
|
export function deleteApi(id: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/openiddict/applications/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询应用 |
||||
|
* @param id 应用id |
||||
|
* @returns 应用实体数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(id: string): Promise<OpenIddictApplicationDto> { |
||||
|
return requestClient.get<OpenIddictApplicationDto>(`/api/openiddict/applications/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新应用 |
||||
|
* @param id 应用id |
||||
|
* @param input 更新参数 |
||||
|
* @returns 应用实体数据传输对象 |
||||
|
*/ |
||||
|
export function updateApi(id: string, input: OpenIddictApplicationUpdateDto): Promise<OpenIddictApplicationDto> { |
||||
|
return requestClient.put<OpenIddictApplicationDto>(`/api/openiddict/applications/${id}`, input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询应用分页列表 |
||||
|
* @param input 过滤参数 |
||||
|
* @returns 应用实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getPagedListApi( |
||||
|
input?: OpenIddictApplicationGetListInput, |
||||
|
): Promise<PagedResultDto<OpenIddictApplicationDto>> { |
||||
|
return requestClient.get<PagedResultDto<OpenIddictApplicationDto>>("/api/openiddict/applications", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
import type { PagedResultDto } from "#/abp-core"; |
||||
|
import type { OpenIddictAuthorizationDto, OpenIddictAuthorizationGetListInput } from "#/openiddict/authorizations"; |
||||
|
|
||||
|
import requestClient from "../request"; |
||||
|
|
||||
|
/** |
||||
|
* 删除授权 |
||||
|
* @param id 授权id |
||||
|
*/ |
||||
|
export function deleteApi(id: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/openiddict/authorizations/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询授权 |
||||
|
* @param id 授权id |
||||
|
* @returns 授权实体数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(id: string): Promise<OpenIddictAuthorizationDto> { |
||||
|
return requestClient.get<OpenIddictAuthorizationDto>(`/api/openiddict/authorizations/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询授权分页列表 |
||||
|
* @param input 过滤参数 |
||||
|
* @returns 授权实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getPagedListApi( |
||||
|
input?: OpenIddictAuthorizationGetListInput, |
||||
|
): Promise<PagedResultDto<OpenIddictAuthorizationDto>> { |
||||
|
return requestClient.get<PagedResultDto<OpenIddictAuthorizationDto>>("/api/openiddict/authorizations", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
import type { OpenIdConfiguration } from "#/abp-core/openid"; |
||||
|
|
||||
|
import requestClient from "../request"; |
||||
|
|
||||
|
/** |
||||
|
* openid发现端点 |
||||
|
* @returns OpenId配置数据 |
||||
|
*/ |
||||
|
export function discoveryApi(): Promise<OpenIdConfiguration> { |
||||
|
return requestClient.get<OpenIdConfiguration>("/.well-known/openid-configuration"); |
||||
|
} |
||||
@ -0,0 +1,56 @@ |
|||||
|
import type { PagedResultDto } from "#/abp-core"; |
||||
|
import type { |
||||
|
OpenIddictScopeCreateDto, |
||||
|
OpenIddictScopeDto, |
||||
|
OpenIddictScopeGetListInput, |
||||
|
OpenIddictScopeUpdateDto, |
||||
|
} from "#/openiddict/scopes"; |
||||
|
|
||||
|
import requestClient from "../request"; |
||||
|
|
||||
|
/** |
||||
|
* 创建范围 |
||||
|
* @param input 参数 |
||||
|
* @returns 范围实体数据传输对象 |
||||
|
*/ |
||||
|
export function createApi(input: OpenIddictScopeCreateDto): Promise<OpenIddictScopeDto> { |
||||
|
return requestClient.post<OpenIddictScopeDto>("/api/openiddict/scopes", input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除范围 |
||||
|
* @param id 范围id |
||||
|
*/ |
||||
|
export function deleteApi(id: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/openiddict/scopes/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取范围 |
||||
|
* @param id 范围id |
||||
|
* @returns 范围实体数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(id: string): Promise<OpenIddictScopeDto> { |
||||
|
return requestClient.get<OpenIddictScopeDto>(`/api/openiddict/scopes/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 更新范围 |
||||
|
* @param id 范围id |
||||
|
* @param input 更新参数 |
||||
|
* @returns 范围实体数据传输对象 |
||||
|
*/ |
||||
|
export function updateApi(id: string, input: OpenIddictScopeUpdateDto): Promise<OpenIddictScopeDto> { |
||||
|
return requestClient.put<OpenIddictScopeDto>(`/api/openiddict/scopes/${id}`, input); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取范围分页列表 |
||||
|
* @param input 过滤参数 |
||||
|
* @returns 范围实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getPagedListApi(input?: OpenIddictScopeGetListInput): Promise<PagedResultDto<OpenIddictScopeDto>> { |
||||
|
return requestClient.get<PagedResultDto<OpenIddictScopeDto>>("/api/openiddict/scopes", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
import type { PagedResultDto } from "#/abp-core"; |
||||
|
import type { OpenIddictTokenDto, OpenIddictTokenGetListInput } from "#/openiddict/tokens"; |
||||
|
import requestClient from "../request"; |
||||
|
|
||||
|
/** |
||||
|
* 删除令牌 |
||||
|
* @param id 令牌id |
||||
|
*/ |
||||
|
export function deleteApi(id: string): Promise<void> { |
||||
|
return requestClient.delete(`/api/openiddict/tokens/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取令牌 |
||||
|
* @param id 令牌id |
||||
|
* @returns 令牌实体数据传输对象 |
||||
|
*/ |
||||
|
export function getApi(id: string): Promise<OpenIddictTokenDto> { |
||||
|
return requestClient.get<OpenIddictTokenDto>(`/api/openiddict/tokens/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取令牌分页列表 |
||||
|
* @param input 过滤参数 |
||||
|
* @returns 令牌实体数据传输对象分页列表 |
||||
|
*/ |
||||
|
export function getPagedListApi(input?: OpenIddictTokenGetListInput): Promise<PagedResultDto<OpenIddictTokenDto>> { |
||||
|
return requestClient.get<PagedResultDto<OpenIddictTokenDto>>("/api/openiddict/tokens", { |
||||
|
params: input, |
||||
|
}); |
||||
|
} |
||||
@ -0,0 +1,127 @@ |
|||||
|
import { authenticateResponseInterceptor, errorMessageResponseInterceptor, RequestClient } from "@/request-client"; |
||||
|
import useLocaleStore from "@/store/localeI18nStore"; |
||||
|
import useUserStore from "@/store/userStore"; |
||||
|
import userStore from "@/store/userStore"; |
||||
|
import { mapLocaleToAbpLanguageFormat } from "@/utils"; |
||||
|
import { toast } from "sonner"; |
||||
|
import { refreshToken } from "./account/token"; |
||||
|
import { wrapperResult } from "@/utils/abp/request"; |
||||
|
import { handleOAuthError } from "@/utils/abp/handleOAuthError"; |
||||
|
|
||||
|
const requestClient = new RequestClient({ |
||||
|
baseURL: import.meta.env.VITE_APP_BASE_API, |
||||
|
}); |
||||
|
|
||||
|
/** |
||||
|
* 重新认证逻辑 |
||||
|
*/ |
||||
|
async function doReAuthenticate() { |
||||
|
console.warn("Access token or refresh token is invalid or expired. "); |
||||
|
//直接登出
|
||||
|
userStore.getState().actions.clearUserInfoAndToken(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 刷新token逻辑 |
||||
|
*/ |
||||
|
async function doRefreshToken() { |
||||
|
console.debug("try -> Refresh token"); |
||||
|
|
||||
|
const { userToken } = useUserStore.getState(); |
||||
|
if (!userToken.refreshToken) { |
||||
|
console.warn("No refresh token available."); |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
const res = await refreshToken({ refreshToken: userToken.refreshToken }); |
||||
|
|
||||
|
const { tokenType, accessToken, refreshToken: newRefreshToken } = res; |
||||
|
|
||||
|
if (accessToken) { |
||||
|
// 更新 userStore,保存新 token
|
||||
|
useUserStore.getState().actions.setUserToken({ |
||||
|
accessToken: `${tokenType} ${accessToken}`, |
||||
|
refreshToken: newRefreshToken, |
||||
|
}); |
||||
|
console.debug("Token refreshed successfully."); |
||||
|
return `${tokenType} ${accessToken}`; // 返回新 token 供拦截器使用
|
||||
|
} |
||||
|
|
||||
|
console.error("Failed to refresh token: No access token returned."); |
||||
|
return ""; |
||||
|
} catch (error) { |
||||
|
console.error("Error refreshing token:", error); |
||||
|
return ""; // 返回空字符串,触发重登录逻辑
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function formatToken(token: null | string) { |
||||
|
return token ? token : null; //有个tokenType的获取值
|
||||
|
} |
||||
|
|
||||
|
// 请求头处理
|
||||
|
requestClient.addRequestInterceptor({ |
||||
|
fulfilled: async (config) => { |
||||
|
const { userToken } = useUserStore.getState(); |
||||
|
if (userToken.accessToken) { |
||||
|
config.headers.Authorization = `${userToken.accessToken}`; |
||||
|
} |
||||
|
const { locale } = useLocaleStore.getState(); |
||||
|
config.headers["Accept-Language"] = mapLocaleToAbpLanguageFormat(locale); |
||||
|
config.headers["X-Request-From"] = "slash-admin"; |
||||
|
return config; |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
// response数据解构
|
||||
|
requestClient.addResponseInterceptor<any>({ |
||||
|
fulfilled: (response) => { |
||||
|
const { data, status } = response; |
||||
|
const { hasWrapResult, getData } = wrapperResult(response); |
||||
|
|
||||
|
if (hasWrapResult()) { |
||||
|
return getData(); |
||||
|
} |
||||
|
|
||||
|
if (status >= 200 && status < 400) { |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
throw Object.assign({}, response, { response }); |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
// token过期的处理
|
||||
|
requestClient.addResponseInterceptor( |
||||
|
authenticateResponseInterceptor({ |
||||
|
client: requestClient, |
||||
|
doReAuthenticate, |
||||
|
doRefreshToken, |
||||
|
enableRefreshToken: true, |
||||
|
formatToken, |
||||
|
}), |
||||
|
); |
||||
|
|
||||
|
// 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
|
||||
|
requestClient.addResponseInterceptor( |
||||
|
errorMessageResponseInterceptor((msg: string, error) => { |
||||
|
// 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg
|
||||
|
// 当前mock接口返回的错误字段是 error 或者 message
|
||||
|
const responseData = error?.response?.data ?? {}; |
||||
|
if (responseData?.error_description) { |
||||
|
const { formatError } = handleOAuthError(); |
||||
|
toast.error(formatError(responseData) || msg, { |
||||
|
position: "top-center", |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
const errorMessage = responseData?.error ?? responseData?.message ?? ""; |
||||
|
// 如果没有错误信息,则会根据状态码进行提示
|
||||
|
toast.error(errorMessage || msg, { |
||||
|
position: "top-center", |
||||
|
}); |
||||
|
}), |
||||
|
); |
||||
|
|
||||
|
export default requestClient; |
||||
@ -0,0 +1,11 @@ |
|||||
|
import apiClient from "../apiClient"; |
||||
|
|
||||
|
export enum DemoApi { |
||||
|
TOKEN_EXPIRED = "/user/tokenExpired", |
||||
|
} |
||||
|
|
||||
|
const mockTokenExpired = () => apiClient.post({ url: DemoApi.TOKEN_EXPIRED }); |
||||
|
|
||||
|
export default { |
||||
|
mockTokenExpired, |
||||
|
}; |
||||
@ -0,0 +1,13 @@ |
|||||
|
import apiClient from "../apiClient"; |
||||
|
|
||||
|
import type { Organization } from "#/entity"; |
||||
|
|
||||
|
export enum OrgApi { |
||||
|
Org = "/org", |
||||
|
} |
||||
|
|
||||
|
const getOrgList = () => apiClient.get<Organization[]>({ url: OrgApi.Org }); |
||||
|
|
||||
|
export default { |
||||
|
getOrgList, |
||||
|
}; |
||||
@ -0,0 +1,33 @@ |
|||||
|
import apiClient from "../apiClient"; |
||||
|
|
||||
|
import type { UserInfo, UserToken } from "#/entity"; |
||||
|
|
||||
|
export interface SignInReq { |
||||
|
username: string; |
||||
|
password: string; |
||||
|
} |
||||
|
|
||||
|
export interface SignUpReq extends SignInReq { |
||||
|
email: string; |
||||
|
} |
||||
|
export type SignInRes = UserToken & { user: UserInfo }; |
||||
|
|
||||
|
export enum UserApi { |
||||
|
SignIn = "/auth/signin", |
||||
|
SignUp = "/auth/signup", |
||||
|
Logout = "/auth/logout", |
||||
|
Refresh = "/auth/refresh", |
||||
|
User = "/user", |
||||
|
} |
||||
|
|
||||
|
const signin = (data: SignInReq) => apiClient.post<SignInRes>({ url: UserApi.SignIn, data }); |
||||
|
const signup = (data: SignUpReq) => apiClient.post<SignInRes>({ url: UserApi.SignUp, data }); |
||||
|
const logout = () => apiClient.get({ url: UserApi.Logout }); |
||||
|
const findById = (id: string) => apiClient.get<UserInfo[]>({ url: `${UserApi.User}/${id}` }); |
||||
|
|
||||
|
export default { |
||||
|
signin, |
||||
|
signup, |
||||
|
findById, |
||||
|
logout, |
||||
|
}; |
||||
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 418 B |
|
After Width: | Height: | Size: 351 B |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 767 B |
|
After Width: | Height: | Size: 710 B |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 346 B |
|
After Width: | Height: | Size: 356 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 509 B |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 735 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |