提交项目所有代码
This commit is contained in:
parent
dd2da96e84
commit
67f6fdf610
11
.editorconfig
Normal file
11
.editorconfig
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Editor configuration, see http://editorconfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
60
.env
Normal file
60
.env
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# the base url of the application, the default is "/"
|
||||||
|
# if use a sub directory, it must be end with "/", like "/admin/" but not "/admin"
|
||||||
|
VITE_BASE_URL=/
|
||||||
|
|
||||||
|
VITE_APP_TITLE=SoybeanAdmin
|
||||||
|
|
||||||
|
VITE_APP_DESC=SoybeanAdmin is a fresh and elegant admin template
|
||||||
|
|
||||||
|
# the prefix of the icon name
|
||||||
|
VITE_ICON_PREFIX=icon
|
||||||
|
|
||||||
|
# the prefix of the local svg icon component, must include VITE_ICON_PREFIX
|
||||||
|
# format {VITE_ICON_PREFIX}-{local icon name}
|
||||||
|
VITE_ICON_LOCAL_PREFIX=icon-local
|
||||||
|
|
||||||
|
# auth route mode: static | dynamic
|
||||||
|
VITE_AUTH_ROUTE_MODE=dynamic
|
||||||
|
|
||||||
|
# static auth route home
|
||||||
|
VITE_ROUTE_HOME=home
|
||||||
|
|
||||||
|
# default menu icon
|
||||||
|
VITE_MENU_ICON=mdi:menu
|
||||||
|
|
||||||
|
# whether to enable http proxy when is dev mode
|
||||||
|
VITE_HTTP_PROXY=Y
|
||||||
|
|
||||||
|
# vue-router mode: hash | history | memory
|
||||||
|
VITE_ROUTER_HISTORY_MODE=history
|
||||||
|
|
||||||
|
# success code of backend service, when the code is received, the request is successful
|
||||||
|
VITE_SERVICE_SUCCESS_CODE=0000
|
||||||
|
|
||||||
|
# logout codes of backend service, when the code is received, the user will be logged out and redirected to login page
|
||||||
|
VITE_SERVICE_LOGOUT_CODES=8888,8889
|
||||||
|
|
||||||
|
# modal logout codes of backend service, when the code is received, the user will be logged out by displaying a modal
|
||||||
|
VITE_SERVICE_MODAL_LOGOUT_CODES=7777,7778
|
||||||
|
|
||||||
|
# token expired codes of backend service, when the code is received, it will refresh the token and resend the request
|
||||||
|
VITE_SERVICE_EXPIRED_TOKEN_CODES=9999,9998,3333
|
||||||
|
|
||||||
|
# when the route mode is static, the defined super role
|
||||||
|
VITE_STATIC_SUPER_ROLE=R_SUPER
|
||||||
|
|
||||||
|
# sourcemap
|
||||||
|
VITE_SOURCE_MAP=N
|
||||||
|
|
||||||
|
# Used to differentiate storage across different domains
|
||||||
|
VITE_STORAGE_PREFIX=SOY_
|
||||||
|
|
||||||
|
# used to control whether the program automatically detects updates
|
||||||
|
VITE_AUTOMATICALLY_DETECT_UPDATE=Y
|
||||||
|
|
||||||
|
# show proxy url log in terminal
|
||||||
|
VITE_PROXY_LOG=Y
|
||||||
|
|
||||||
|
# used to control whether to launch editor
|
||||||
|
# by the way, this plugin is only available in dev mode, not in build mode
|
||||||
|
VITE_DEVTOOLS_LAUNCH_EDITOR=code
|
||||||
7
.env.prod
Normal file
7
.env.prod
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# backend service base url, prod environment
|
||||||
|
VITE_SERVICE_BASE_URL=http://localhost:8080
|
||||||
|
|
||||||
|
# other backend service base url, prod environment
|
||||||
|
VITE_OTHER_SERVICE_BASE_URL= `{
|
||||||
|
"demo": "http://localhost:9529"
|
||||||
|
}`
|
||||||
7
.env.test
Normal file
7
.env.test
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# backend service base url, test environment
|
||||||
|
VITE_SERVICE_BASE_URL=http://localhost:8080
|
||||||
|
|
||||||
|
# other backend service base url, test environment
|
||||||
|
VITE_OTHER_SERVICE_BASE_URL= `{
|
||||||
|
"demo": "http://localhost:9528"
|
||||||
|
}`
|
||||||
13
.gitattributes
vendored
Normal file
13
.gitattributes
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
"*.vue" eol=lf
|
||||||
|
"*.js" eol=lf
|
||||||
|
"*.ts" eol=lf
|
||||||
|
"*.jsx" eol=lf
|
||||||
|
"*.tsx" eol=lf
|
||||||
|
"*.mjs" eol=lf
|
||||||
|
"*.json" eol=lf
|
||||||
|
"*.html" eol=lf
|
||||||
|
"*.css" eol=lf
|
||||||
|
"*.scss" eol=lf
|
||||||
|
"*.md" eol=lf
|
||||||
|
"*.yaml" eol=lf
|
||||||
|
"*.yml" eol=lf
|
||||||
90
.github/ISSUE_TEMPLATE/bug-report_cn.yaml
vendored
Normal file
90
.github/ISSUE_TEMPLATE/bug-report_cn.yaml
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
name: 🐞 Bug提交
|
||||||
|
description: 在使用软件或功能的过程中遇到了错误
|
||||||
|
title: '[Bug]: '
|
||||||
|
labels: [ "bug?" ]
|
||||||
|
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
## 请按照以下要求进行提交
|
||||||
|
### 1. 提交后需要指定标签和截止时间。
|
||||||
|
---
|
||||||
|
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
## 环境信息
|
||||||
|
请根据实际使用环境修改以下信息。
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: env-program-ver
|
||||||
|
attributes:
|
||||||
|
label: 软件版本
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: env-vm-ver
|
||||||
|
attributes:
|
||||||
|
label: 运行环境
|
||||||
|
description: 选择运行软件的系统版本
|
||||||
|
options:
|
||||||
|
- Windows (64)
|
||||||
|
- Windows (32/x84)
|
||||||
|
- MacOS
|
||||||
|
- Linux
|
||||||
|
- Ubuntu
|
||||||
|
- CentOS
|
||||||
|
- ArchLinux
|
||||||
|
- UNIX (Android)
|
||||||
|
- 其它(请在下方说明)
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: env-vm-arch
|
||||||
|
attributes:
|
||||||
|
label: 运行架构
|
||||||
|
description: (可选) 选择运行软件的系统架构
|
||||||
|
options:
|
||||||
|
- AMD64
|
||||||
|
- x86
|
||||||
|
- ARM [32] (别名:AArch32 / ARMv7)
|
||||||
|
- ARM [64] (别名:AArch64 / ARMv8)
|
||||||
|
- 其它
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: reproduce-steps
|
||||||
|
attributes:
|
||||||
|
label: 重现步骤
|
||||||
|
description: |
|
||||||
|
我们需要执行哪些操作才能让 bug 出现?
|
||||||
|
简洁清晰的重现步骤能够帮助我们更迅速地定位问题所在。
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: expected
|
||||||
|
attributes:
|
||||||
|
label: 期望的结果是什么?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: actual
|
||||||
|
attributes:
|
||||||
|
label: 实际的结果是什么?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: logging
|
||||||
|
attributes:
|
||||||
|
label: 日志记录(可选)
|
||||||
|
render: golang
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: extra-desc
|
||||||
|
attributes:
|
||||||
|
label: 补充说明(可选)
|
||||||
90
.github/ISSUE_TEMPLATE/bug-report_en.yaml
vendored
Normal file
90
.github/ISSUE_TEMPLATE/bug-report_en.yaml
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
name: 🐞 Bug Report
|
||||||
|
description: Encountered an error while using the software or feature
|
||||||
|
title: '[Bug]: '
|
||||||
|
labels: [ "bug?" ]
|
||||||
|
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
## Please submit according to the following requirements
|
||||||
|
### 1. After submission, you need to specify the label and deadline.
|
||||||
|
---
|
||||||
|
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
## Environment Information
|
||||||
|
Please modify the following information according to the actual usage environment.
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: env-program-ver
|
||||||
|
attributes:
|
||||||
|
label: Software Version
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: env-vm-ver
|
||||||
|
attributes:
|
||||||
|
label: Operating Environment
|
||||||
|
description: Select the system version on which the software is running
|
||||||
|
options:
|
||||||
|
- Windows (64)
|
||||||
|
- Windows (32/x84)
|
||||||
|
- MacOS
|
||||||
|
- Linux
|
||||||
|
- Ubuntu
|
||||||
|
- CentOS
|
||||||
|
- ArchLinux
|
||||||
|
- UNIX (Android)
|
||||||
|
- Other (please specify below)
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: env-vm-arch
|
||||||
|
attributes:
|
||||||
|
label: Operating Architecture
|
||||||
|
description: (Optional) Select the system architecture on which the software is running
|
||||||
|
options:
|
||||||
|
- AMD64
|
||||||
|
- x86
|
||||||
|
- ARM [32] (Alias:AArch32 / ARMv7)
|
||||||
|
- ARM [64] (Alias:AArch64 / ARMv8)
|
||||||
|
- Other
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: reproduce-steps
|
||||||
|
attributes:
|
||||||
|
label: Reproduce Steps
|
||||||
|
description: |
|
||||||
|
What operations do we need to perform to make the bug appear?
|
||||||
|
The concise and clear reproduction steps can help us locate the problem more quickly.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: expected
|
||||||
|
attributes:
|
||||||
|
label: What is the expected result?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: actual
|
||||||
|
attributes:
|
||||||
|
label: What is the actual result?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: logging
|
||||||
|
attributes:
|
||||||
|
label: Logging (Optional)
|
||||||
|
render: golang
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: extra-desc
|
||||||
|
attributes:
|
||||||
|
label: Additional Description (Optional)
|
||||||
48
.github/ISSUE_TEMPLATE/feature_request_cn.yaml
vendored
Normal file
48
.github/ISSUE_TEMPLATE/feature_request_cn.yaml
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
name: 🚀 功能请求
|
||||||
|
description: 提出一个想法以帮助我们改进W&B
|
||||||
|
title: "[功能]: "
|
||||||
|
labels:
|
||||||
|
- "功能请求"
|
||||||
|
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
**感谢 :heart: 您花时间填写此功能请求报告!**
|
||||||
|
我们恳请您搜索看看您的功能是否[已经存在](https://github.com/soybeanjs/soybean-admin/issues?q=is%3Aissue+sort%3Acreated-desc+)。
|
||||||
|
|
||||||
|
我们也很乐意接受用户的贡献。有关更多详细信息,请参阅[此处](https://github.com/soybeanjs/soybean-admin/blob/main/README.zh_CN.md#%E5%A6%82%E4%BD%95%E8%B4%A1%E7%8C%AE)。
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 描述
|
||||||
|
description: |
|
||||||
|
对您感兴趣的功能的清晰简洁的描述。
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 建议的解决方案
|
||||||
|
description: |
|
||||||
|
描述您想要的解决方案。对您希望发生的事情的清晰简洁的描述。
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 替代方案
|
||||||
|
description: |
|
||||||
|
描述您考虑过的替代方案。
|
||||||
|
对您考虑过的任何替代解决方案或功能的清晰简洁的描述。
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 额外的上下文
|
||||||
|
description: |
|
||||||
|
在此处添加有关问题的其他上下文。
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
48
.github/ISSUE_TEMPLATE/feature_request_en.yaml
vendored
Normal file
48
.github/ISSUE_TEMPLATE/feature_request_en.yaml
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
name: 🚀 Feature Request
|
||||||
|
description: Suggest an idea to help us improve W&B
|
||||||
|
title: "[Feature]: "
|
||||||
|
labels:
|
||||||
|
- "feature_request"
|
||||||
|
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
**Thanks :heart: for taking the time to fill out this feature request report!**
|
||||||
|
We kindly ask that you search to see if an issue [already exists](https://github.com/soybeanjs/soybean-admin/issues?q=is%3Aissue+sort%3Acreated-desc+) for your feature.
|
||||||
|
|
||||||
|
We are also happy to accept contributions from our users. For more details see [here](https://github.com/soybeanjs/soybean-admin/blob/main/README.md#how-to-contribute).
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: |
|
||||||
|
A clear and concise description of the feature you're interested in.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Suggested Solution
|
||||||
|
description: |
|
||||||
|
Describe the solution you'd like. A clear and concise description of what you want to happen.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Alternatives
|
||||||
|
description: |
|
||||||
|
Describe alternatives you've considered.
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional Context
|
||||||
|
description: |
|
||||||
|
Add any other context about the problem here.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
50
.github/PULL_REQUEST_TEMPLATE/pr_cn.md
vendored
Normal file
50
.github/PULL_REQUEST_TEMPLATE/pr_cn.md
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
首先,感谢你的贡献! 😄
|
||||||
|
|
||||||
|
新特性请提交至 feature 分支,其余可提交至 main 分支。在一个维护者审核通过后合并。请确保填写以下 pull request 的信息,谢谢!~
|
||||||
|
|
||||||
|
[[English Template / 英文模板](./pr_en.md)]
|
||||||
|
|
||||||
|
### 这个变动的性质是
|
||||||
|
|
||||||
|
- [ ] 新特性提交
|
||||||
|
- [ ] 日常 bug 修复
|
||||||
|
- [ ] 站点、文档改进
|
||||||
|
- [ ] 组件样式改进
|
||||||
|
- [ ] TypeScript 定义更新
|
||||||
|
- [ ] 重构
|
||||||
|
- [ ] 代码风格优化
|
||||||
|
- [ ] 分支合并
|
||||||
|
- [ ] 其他改动(是关于什么的改动?)
|
||||||
|
|
||||||
|
### 需求背景
|
||||||
|
|
||||||
|
> 1. 描述相关需求的来源。
|
||||||
|
> 2. 要解决的问题。
|
||||||
|
> 3. 相关的 issue 讨论链接。
|
||||||
|
|
||||||
|
### 实现方案和 API(非新功能可选)
|
||||||
|
|
||||||
|
> 1. 基本的解决思路和其他可选方案。
|
||||||
|
> 2. 列出最终的 API 实现和用法。
|
||||||
|
> 3. 涉及 UI/交互变动需要有截图或 GIF。
|
||||||
|
|
||||||
|
### 对用户的影响和可能的风险(非新功能可选)
|
||||||
|
|
||||||
|
> 1. 这个改动对用户端是否有影响?影响的方面有哪些?
|
||||||
|
> 2. 是否有可能隐含的 break change 和其他风险?
|
||||||
|
|
||||||
|
### Changelog 描述(非新功能可选)
|
||||||
|
|
||||||
|
> 1. 英文描述
|
||||||
|
> 2. 中文描述(可选)
|
||||||
|
|
||||||
|
### 请求合并前的自查清单
|
||||||
|
|
||||||
|
- [ ] 文档已补充或无须补充
|
||||||
|
- [ ] 代码演示已提供或无须提供
|
||||||
|
- [ ] TypeScript 定义已补充或无须补充
|
||||||
|
- [ ] Changelog 已提供或无须提供
|
||||||
|
|
||||||
|
### 后续计划(非新功能可选)
|
||||||
|
|
||||||
|
> 如果这个提交后面还有相关的其他提交和跟进信息,可以写在这里。
|
||||||
51
.github/PULL_REQUEST_TEMPLATE/pr_en.md
vendored
Normal file
51
.github/PULL_REQUEST_TEMPLATE/pr_en.md
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
First of all, thank you for your contribution! 😄
|
||||||
|
|
||||||
|
New feature please send pull request to feature branch, and rest to main branch. Pull request will be merged after one of collaborators approve. Please makes sure that these form are filled before submitting your pull request, thank you!
|
||||||
|
|
||||||
|
[[中文版模板 / Chinese template](./pr_cn.md)]
|
||||||
|
|
||||||
|
### This is a ...
|
||||||
|
|
||||||
|
- [ ] New feature
|
||||||
|
- [ ] Bug fix
|
||||||
|
- [ ] Site / document update
|
||||||
|
- [ ] Component style update
|
||||||
|
- [ ] TypeScript definition update
|
||||||
|
- [ ] Refactoring
|
||||||
|
- [ ] Code style optimization
|
||||||
|
- [ ] Branch merge
|
||||||
|
- [ ] Other (about what?)
|
||||||
|
|
||||||
|
### What's the background?
|
||||||
|
|
||||||
|
> 1. Describe the source of requirement.
|
||||||
|
> 2. Resolve what problem.
|
||||||
|
> 3. Related issue link.
|
||||||
|
|
||||||
|
### API Realization (Optional if not new feature)
|
||||||
|
|
||||||
|
> 1. Basic thought of solution and other optional proposal.
|
||||||
|
> 2. List final API realization and usage sample.
|
||||||
|
> 3. GIF or snapshot should be provided if includes UI/interactive modification.
|
||||||
|
|
||||||
|
### What's the effect? (Optional if not new feature)
|
||||||
|
|
||||||
|
> 1. Does this PR affect user? Which part will be affected?
|
||||||
|
> 2. What will say in changelog?
|
||||||
|
> 3. Does this PR contains potential break change or other risk?
|
||||||
|
|
||||||
|
### Changelog description (Optional if not new feature)
|
||||||
|
|
||||||
|
> 1. English description
|
||||||
|
> 2. Chinese description (optional)
|
||||||
|
|
||||||
|
### Self Check before Merge
|
||||||
|
|
||||||
|
- [ ] Doc is updated/provided or not needed
|
||||||
|
- [ ] Demo is updated/provided or not needed
|
||||||
|
- [ ] TypeScript definition is updated/provided or not needed
|
||||||
|
- [ ] Changelog is provided or not needed
|
||||||
|
|
||||||
|
### Additional Plan? (Optional if not new feature)
|
||||||
|
|
||||||
|
> If this PR related with other PR or following info. You can type here.
|
||||||
30
.github/workflows/linter.yml
vendored
Normal file
30
.github/workflows/linter.yml
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
name: Lint Code
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
name: Lint All Code
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Lint Code Base
|
||||||
|
uses: github/super-linter@v4
|
||||||
|
env:
|
||||||
|
VALIDATE_ALL_CODEBASE: false
|
||||||
|
DEFAULT_BRANCH: main
|
||||||
|
# To change branch master or main
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
FILTER_REGEX_EXCLUDE: (docs|.github)
|
||||||
|
VALIDATE_MARKDOWN: false
|
||||||
25
.github/workflows/release.yml
vendored
Normal file
25
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 18.x
|
||||||
|
|
||||||
|
- run: npx githublogen
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||||
35
.gitignore
vendored
Normal file
35
.gitignore
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
.DS_Store
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
coverage
|
||||||
|
*.local
|
||||||
|
|
||||||
|
/cypress/videos/
|
||||||
|
/cypress/screenshots/
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
.idea
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
|
||||||
|
.VSCodeCounter
|
||||||
4
.npmrc
Normal file
4
.npmrc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
registry=https://registry.npmmirror.com/
|
||||||
|
shamefully-hoist=true
|
||||||
|
ignore-workspace-root-check=true
|
||||||
|
link-workspace-packages=true
|
||||||
19
.vscode/extensions.json
vendored
Normal file
19
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"afzalsayed96.icones",
|
||||||
|
"antfu.iconify",
|
||||||
|
"antfu.unocss",
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"editorconfig.editorconfig",
|
||||||
|
"lokalise.i18n-ally",
|
||||||
|
"mhutchie.git-graph",
|
||||||
|
"mikestead.dotenv",
|
||||||
|
"naumovs.color-highlight",
|
||||||
|
"pkief.material-icon-theme",
|
||||||
|
"sdras.vue-vscode-snippets",
|
||||||
|
"vue.volar",
|
||||||
|
"whtouche.vscode-js-console-utils",
|
||||||
|
"zhuangtongfa.material-theme",
|
||||||
|
"tu6ge.naive-ui-intelligence"
|
||||||
|
]
|
||||||
|
}
|
||||||
22
.vscode/launch.json
vendored
Normal file
22
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Vue Debugger",
|
||||||
|
"url": "http://localhost:9527",
|
||||||
|
"webRoot": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "TS Debugger",
|
||||||
|
"runtimeExecutable": "tsx",
|
||||||
|
"skipFiles": ["<node_internals>/**", "${workspaceFolder}/node_modules/**"],
|
||||||
|
"program": "${file}",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"internalConsoleOptions": "neverOpen"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
31
.vscode/settings.json
vendored
Normal file
31
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.eslint": "explicit",
|
||||||
|
"source.organizeImports": "never"
|
||||||
|
},
|
||||||
|
"editor.formatOnSave": false,
|
||||||
|
"eslint.validate": [
|
||||||
|
"html",
|
||||||
|
"css",
|
||||||
|
"scss",
|
||||||
|
"json",
|
||||||
|
"jsonc",
|
||||||
|
"javascript",
|
||||||
|
"javascriptreact",
|
||||||
|
"typescript",
|
||||||
|
"typescriptreact",
|
||||||
|
"vue"
|
||||||
|
],
|
||||||
|
"i18n-ally.displayLanguage": "zh-cn",
|
||||||
|
"i18n-ally.enabledParsers": ["ts"],
|
||||||
|
"i18n-ally.enabledFrameworks": ["vue"],
|
||||||
|
"i18n-ally.editor.preferEditor": true,
|
||||||
|
"i18n-ally.keystyle": "nested",
|
||||||
|
"i18n-ally.localesPaths": ["src/locales/langs"],
|
||||||
|
"i18n-ally.parsers.typescript.compilerOptions": {
|
||||||
|
"moduleResolution": "node"
|
||||||
|
},
|
||||||
|
"prettier.enable": false,
|
||||||
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
|
"unocss.root": ["./"]
|
||||||
|
}
|
||||||
258
BACKEND_SETUP.md
Normal file
258
BACKEND_SETUP.md
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
# Spring Boot 后端配置指南
|
||||||
|
|
||||||
|
## 已完成的工作
|
||||||
|
|
||||||
|
我已经为你创建了一个完整的 Spring Boot 后端项目,包含以下功能:
|
||||||
|
|
||||||
|
### ✅ 实现的接口
|
||||||
|
|
||||||
|
1. **认证接口**
|
||||||
|
- `POST /auth/login` - 用户登录
|
||||||
|
- `GET /auth/getUserInfo` - 获取用户信息
|
||||||
|
- `POST /auth/refreshToken` - 刷新令牌
|
||||||
|
- `GET /auth/error` - 自定义错误
|
||||||
|
|
||||||
|
2. **路由接口**
|
||||||
|
- `GET /route/getConstantRoutes` - 获取常量路由
|
||||||
|
- `GET /route/getUserRoutes` - 获取用户路由
|
||||||
|
- `GET /route/isRouteExist` - 检查路由是否存在
|
||||||
|
|
||||||
|
### 📁 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
backend/
|
||||||
|
├── pom.xml # Maven 配置
|
||||||
|
├── src/main/
|
||||||
|
│ ├── java/com/soybean/admin/
|
||||||
|
│ │ ├── SoybeanAdminApplication.java # 启动类
|
||||||
|
│ │ ├── common/
|
||||||
|
│ │ │ └── Result.java # 统一响应格式
|
||||||
|
│ │ ├── config/
|
||||||
|
│ │ │ ├── WebConfig.java # Web 配置(CORS)
|
||||||
|
│ │ │ └── InterceptorConfig.java # 拦截器配置
|
||||||
|
│ │ ├── controller/
|
||||||
|
│ │ │ ├── AuthController.java # 认证控制器
|
||||||
|
│ │ │ └── RouteController.java # 路由控制器
|
||||||
|
│ │ ├── dto/ # 数据传输对象
|
||||||
|
│ │ ├── entity/
|
||||||
|
│ │ │ ├── User.java # 用户实体
|
||||||
|
│ │ │ └── Route.java # 路由实体
|
||||||
|
│ │ ├── exception/
|
||||||
|
│ │ │ └── GlobalExceptionHandler.java # 全局异常处理
|
||||||
|
│ │ ├── interceptor/
|
||||||
|
│ │ │ └── AuthInterceptor.java # JWT 认证拦截器
|
||||||
|
│ │ ├── mapper/
|
||||||
|
│ │ │ ├── UserMapper.java # 用户 Mapper
|
||||||
|
│ │ │ └── RouteMapper.java # 路由 Mapper
|
||||||
|
│ │ ├── service/
|
||||||
|
│ │ │ ├── AuthService.java # 认证服务
|
||||||
|
│ │ │ └── RouteService.java # 路由服务
|
||||||
|
│ │ └── util/
|
||||||
|
│ │ └── JwtUtil.java # JWT 工具类
|
||||||
|
│ └── resources/
|
||||||
|
│ ├── application.yml # 应用配置
|
||||||
|
│ └── sql/
|
||||||
|
│ └── init.sql # 数据库初始化脚本
|
||||||
|
├── start.bat # Windows 启动脚本
|
||||||
|
└── README.md # 项目说明文档
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 启动步骤
|
||||||
|
|
||||||
|
### 1. 初始化数据库
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 方式一:使用 MySQL 命令行
|
||||||
|
mysql -u root -p < backend/src/main/resources/sql/init.sql
|
||||||
|
|
||||||
|
# 方式二:登录 MySQL 后执行
|
||||||
|
mysql -u root -p
|
||||||
|
source backend/src/main/resources/sql/init.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
这将创建:
|
||||||
|
- 数据库:`soybean_admin`
|
||||||
|
- 表:`sys_user`(用户表)、`sys_route`(路由表)
|
||||||
|
- 默认用户:
|
||||||
|
- 管理员:admin / admin123
|
||||||
|
- 普通用户:user / user123
|
||||||
|
|
||||||
|
### 2. 启动后端服务
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 进入后端目录
|
||||||
|
cd backend
|
||||||
|
|
||||||
|
# 方式一:使用 Maven 启动
|
||||||
|
mvn spring-boot:run
|
||||||
|
|
||||||
|
# 方式二:Windows 双击启动脚本
|
||||||
|
start.bat
|
||||||
|
|
||||||
|
# 方式三:编译后运行
|
||||||
|
mvn clean package
|
||||||
|
java -jar target/soybean-admin-backend-1.0.0.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
服务将在 `http://localhost:8080` 启动。
|
||||||
|
|
||||||
|
### 3. 配置前端连接后端
|
||||||
|
|
||||||
|
修改前端项目的环境配置文件:
|
||||||
|
|
||||||
|
**`.env.test`** (开发环境)
|
||||||
|
```env
|
||||||
|
# 将 Mock 地址改为本地后端地址
|
||||||
|
VITE_SERVICE_BASE_URL=http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
**`.env.prod`** (生产环境)
|
||||||
|
```env
|
||||||
|
# 生产环境后端地址
|
||||||
|
VITE_SERVICE_BASE_URL=http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 启动前端项目
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 安装依赖(如果还没安装)
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# 启动开发服务器
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧪 测试接口
|
||||||
|
|
||||||
|
### 使用 curl 测试登录
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8080/auth/login \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"userName\":\"admin\",\"password\":\"admin123\"}"
|
||||||
|
```
|
||||||
|
|
||||||
|
预期响应:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "0000",
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"token": "eyJhbGc...",
|
||||||
|
"refreshToken": "eyJhbGc..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用 token 获取用户信息
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X GET http://localhost:8080/auth/getUserInfo \
|
||||||
|
-H "Authorization: Bearer YOUR_TOKEN_HERE"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 数据库表结构
|
||||||
|
|
||||||
|
### sys_user (用户表)
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| id | BIGINT | 主键 |
|
||||||
|
| user_id | VARCHAR(50) | 用户ID |
|
||||||
|
| user_name | VARCHAR(50) | 用户名 |
|
||||||
|
| password | VARCHAR(100) | 密码 |
|
||||||
|
| roles | VARCHAR(200) | 角色(逗号分隔) |
|
||||||
|
| buttons | VARCHAR(500) | 按钮权限(逗号分隔) |
|
||||||
|
| status | INT | 状态:1-启用,2-禁用 |
|
||||||
|
| deleted | INT | 删除标记 |
|
||||||
|
| create_time | DATETIME | 创建时间 |
|
||||||
|
| update_time | DATETIME | 更新时间 |
|
||||||
|
|
||||||
|
### sys_route (路由表)
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| id | BIGINT | 主键 |
|
||||||
|
| route_id | VARCHAR(50) | 路由ID |
|
||||||
|
| name | VARCHAR(50) | 路由名称 |
|
||||||
|
| path | VARCHAR(200) | 路由路径 |
|
||||||
|
| component | VARCHAR(200) | 组件路径 |
|
||||||
|
| meta | TEXT | 元信息(JSON) |
|
||||||
|
| roles | VARCHAR(200) | 可访问角色 |
|
||||||
|
| order_num | INT | 排序号 |
|
||||||
|
| status | INT | 状态 |
|
||||||
|
| deleted | INT | 删除标记 |
|
||||||
|
| create_time | DATETIME | 创建时间 |
|
||||||
|
| update_time | DATETIME | 更新时间 |
|
||||||
|
|
||||||
|
## 🔐 默认账号
|
||||||
|
|
||||||
|
| 用户名 | 密码 | 角色 | 权限 |
|
||||||
|
|--------|------|------|------|
|
||||||
|
| admin | admin123 | R_SUPER, R_ADMIN | 所有权限 |
|
||||||
|
| user | user123 | R_USER | 查看权限 |
|
||||||
|
|
||||||
|
## ⚙️ 配置说明
|
||||||
|
|
||||||
|
### JWT 配置
|
||||||
|
在 `application.yml` 中:
|
||||||
|
```yaml
|
||||||
|
jwt:
|
||||||
|
secret: soybean-admin-secret-key-2024-spring-boot-jwt-token
|
||||||
|
expiration: 7200000 # 2小时
|
||||||
|
refresh-expiration: 604800000 # 7天
|
||||||
|
```
|
||||||
|
|
||||||
|
### 数据库配置
|
||||||
|
```yaml
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
url: jdbc:mysql://localhost:3306/soybean_admin
|
||||||
|
username: root
|
||||||
|
password: root
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 下一步
|
||||||
|
|
||||||
|
1. **添加新菜单**:在数据库 `sys_route` 表中插入新路由
|
||||||
|
2. **添加新用户**:在数据库 `sys_user` 表中插入新用户
|
||||||
|
3. **权限控制**:通过 `roles` 字段控制路由访问权限
|
||||||
|
4. **密码加密**:建议在生产环境使用 BCrypt 加密密码
|
||||||
|
|
||||||
|
## ❗ 注意事项
|
||||||
|
|
||||||
|
1. **生产环境**:
|
||||||
|
- 修改 JWT 密钥
|
||||||
|
- 使用密码加密(BCrypt)
|
||||||
|
- 配置 HTTPS
|
||||||
|
- 添加日志文件输出
|
||||||
|
- 配置数据库连接池
|
||||||
|
|
||||||
|
2. **开发环境**:
|
||||||
|
- 确保 MySQL 服务已启动
|
||||||
|
- 确保端口 8080 未被占用
|
||||||
|
- 检查 Java 版本(需要 JDK 17+)
|
||||||
|
|
||||||
|
## 🐛 常见问题
|
||||||
|
|
||||||
|
### 1. 端口被占用
|
||||||
|
修改 `application.yml` 中的端口:
|
||||||
|
```yaml
|
||||||
|
server:
|
||||||
|
port: 8081
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 数据库连接失败
|
||||||
|
检查 MySQL 服务是否启动,用户名密码是否正确。
|
||||||
|
|
||||||
|
### 3. Maven 依赖下载慢
|
||||||
|
配置国内镜像源(阿里云)。
|
||||||
|
|
||||||
|
## 📞 技术支持
|
||||||
|
|
||||||
|
如有问题,请查看:
|
||||||
|
- `backend/README.md` - 详细文档
|
||||||
|
- 日志输出 - 查看错误信息
|
||||||
|
- MySQL 日志 - 检查数据库问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
现在你可以开始使用完整的前后端分离系统了!🎉
|
||||||
3317
CHANGELOG.md
Normal file
3317
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
634
CHANGELOG.zh_CN.md
Normal file
634
CHANGELOG.zh_CN.md
Normal file
@ -0,0 +1,634 @@
|
|||||||
|
# 更新日志
|
||||||
|
|
||||||
|
## [v1.3.5](https://github.com/soybeanjs/soybean-admin/compare/v1.3.4...v1.3.5) (2024-09-07)
|
||||||
|
|
||||||
|
### 🚀 新功能
|
||||||
|
|
||||||
|
- **packages**:
|
||||||
|
- @sa/axios: 成功时将响应添加到 flatRequest - by @soybeanjs [<samp>(c4e16)</samp>](https://github.com/soybeanjs/soybean-admin/commit/c4e1610)
|
||||||
|
- **projects**:
|
||||||
|
- README.zh_CN.md 添加合作推广 - by @PZ-18664918826 in https://github.com/soybeanjs/soybean-admin/issues/601 [<samp>(2fa40)</samp>](https://github.com/soybeanjs/soybean-admin/commit/2fa400b)
|
||||||
|
- 根据 Apache 规范添加更多提交类型 - by @Azir-11 in https://github.com/soybeanjs/soybean-admin/issues/610 [<samp>(878d9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/878d9c3)
|
||||||
|
- 配置是否支持自动更新。关闭#612 - by @Azir-11 in https://github.com/soybeanjs/soybean-admin/issues/617 和 https://github.com/soybeanjs/soybean-admin/issues/612 [<samp>(4c9f4)</samp>](https://github.com/soybeanjs/soybean-admin/commit/4c9f4e0)
|
||||||
|
- 添加应用错误处理程序。关闭 #587 - by @soybeanjs in https://github.com/soybeanjs/soybean-admin/issues/587 [<samp>(be855)</samp>](https://github.com/soybeanjs/soybean-admin/commit/be8556c)
|
||||||
|
|
||||||
|
### 🐞 Bug 修复
|
||||||
|
|
||||||
|
- **deps**:
|
||||||
|
- 将 json5 从 devDependencies 移到 dependencies 以支持生产环境使用 - by @mufeng889 in https://github.com/soybeanjs/soybean-admin/issues/618 [<samp>(7cb43)</samp>](https://github.com/soybeanjs/soybean-admin/commit/7cb43fc)
|
||||||
|
- **projects**:
|
||||||
|
- 避免检索缓存的 HTML - by @Azir-11 in https://github.com/soybeanjs/soybean-admin/issues/605 [<samp>(ef6cf)</samp>](https://github.com/soybeanjs/soybean-admin/commit/ef6cf93)
|
||||||
|
- 修复登录重定向 - by @soybeanjs [<samp>(3830e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3830ec7)
|
||||||
|
- 修复侧边栏折叠时的 vertical-mix-menu。修复 #608 - by @soybeanjs in https://github.com/soybeanjs/soybean-admin/issues/608 [<samp>(c3f1f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/c3f1f69)
|
||||||
|
- 修复 activeMenu 为父菜单时的面包屑。修复 #589 - by @soybeanjs in https://github.com/soybeanjs/soybean-admin/issues/589 [<samp>(79b2a)</samp>](https://github.com/soybeanjs/soybean-admin/commit/79b2a28)
|
||||||
|
- 修复遇到多请求时的刷新令牌。修复 #581 - by @soybeanjs in https://github.com/soybeanjs/soybean-admin/issues/581 [<samp>(27b52)</samp>](https://github.com/soybeanjs/soybean-admin/commit/27b5222)
|
||||||
|
- **types**:
|
||||||
|
- 修复 TableApiFn 的类型 - by @Azir-11 in https://github.com/soybeanjs/soybean-admin/issues/599 [<samp>(26c93)</samp>](https://github.com/soybeanjs/soybean-admin/commit/26c93df)
|
||||||
|
|
||||||
|
### 🛠 优化
|
||||||
|
|
||||||
|
- **projects**: 优化菜单 selectedKey - by @soybeanjs [<samp>(531bf)</samp>](https://github.com/soybeanjs/soybean-admin/commit/531bfaf)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **projects**:
|
||||||
|
- 更新 README - by @mufeng889 in https://github.com/soybeanjs/soybean-admin/issues/594 [<samp>(a8f92)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a8f923e)
|
||||||
|
- 更新 README - by @soybeanjs [<samp>(e9a2e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e9a2ee4)
|
||||||
|
- 更新 README - by @soybeanjs [<samp>(73e91)</samp>](https://github.com/soybeanjs/soybean-admin/commit/73e917a)
|
||||||
|
- 更新文档中重要信息的位置 - by **Azir** [<samp>(9c012)</samp>](https://github.com/soybeanjs/soybean-admin/commit/9c012c7)
|
||||||
|
|
||||||
|
### 🏡 杂项
|
||||||
|
|
||||||
|
- **deps**:
|
||||||
|
- 更新依赖 - by @soybeanjs [<samp>(a1c14)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a1c14a1)
|
||||||
|
- 更新依赖 - by @soybeanjs [<samp>(7fa55)</samp>](https://github.com/soybeanjs/soybean-admin/commit/7fa5590)
|
||||||
|
- 更新依赖 - by @soybeanjs [<samp>(a44ea)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a44ea62)
|
||||||
|
- **projects**:
|
||||||
|
- 使用 json5 解析环境变量 `VITE_OTHER_SERVICE_BASE_URL` 并修复代理启用 - by @soybeanjs [<samp>(b16a9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b16a963)
|
||||||
|
|
||||||
|
### 🎨 样式
|
||||||
|
|
||||||
|
- **projects**: 将脚本 czh 重命名为 commit:zh - by @Azir-11 in https://github.com/soybeanjs/soybean-admin/issues/597 [<samp>(5094f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/5094f0e)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/soybeanjs) [](https://github.com/mufeng889) [](https://github.com/Azir-11) [](https://github.com/PZ-18664918826)
|
||||||
|
[Azir](mailto:2075125282@qq.com),
|
||||||
|
|
||||||
|
## [v1.3.4](https://github.com/honghuangdc/soybean-admin/compare/v1.3.3...v1.3.4) (2024-08-01)
|
||||||
|
|
||||||
|
### 🚨 重大变更
|
||||||
|
|
||||||
|
- **projects**: 当 vertical-mix 布局为 mixSiderFixed 时,不重置活动菜单 - by @honghuangdc [<samp>(939c5)</samp>](https://github.com/honghuangdc/soybean-admin/commit/939c512)
|
||||||
|
|
||||||
|
### 🛠 优化
|
||||||
|
|
||||||
|
- **projects**: 优化代码 - by @honghuangdc [<samp>(cb1d4)</samp>](https://github.com/honghuangdc/soybean-admin/commit/cb1d445)
|
||||||
|
|
||||||
|
### 🏡 杂项
|
||||||
|
|
||||||
|
- **projects**: 更新依赖并修复 vue-router 类型 - by @honghuangdc [<samp>(96837)</samp>](https://github.com/honghuangdc/soybean-admin/commit/968370b)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
|
||||||
|
## [v1.3.3](https://github.com/honghuangdc/soybean-admin/compare/v1.3.2...v1.3.3) (2024-07-30)
|
||||||
|
|
||||||
|
### 🐞 Bug 修复
|
||||||
|
|
||||||
|
- **projects**: 修复水印设置 - by @honghuangdc [<samp>(5646a)</samp>](https://github.com/honghuangdc/soybean-admin/commit/5646a50)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **projects**: 更新 CHANGELOG - by @honghuangdc [<samp>(ebc83)</samp>](https://github.com/honghuangdc/soybean-admin/commit/ebc838c)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
|
||||||
|
## [v1.3.2](https://github.com/honghuangdc/soybean-admin/compare/v1.3.1...v1.3.2) (2024-07-30)
|
||||||
|
|
||||||
|
### 🚀 新功能
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 添加颜色渐变模式。关闭 #567 - 由 @Azir-11 在 https://github.com/honghuangdc/soybean-admin/issues/569 和 https://github.com/honghuangdc/soybean-admin/issues/567 [<samp>(4dde4)</samp>](https://github.com/honghuangdc/soybean-admin/commit/4dde4c2)
|
||||||
|
- 添加全屏水印。关闭 #571 - 由 @paynezhuang 在 https://github.com/honghuangdc/soybean-admin/issues/573 和 https://github.com/honghuangdc/soybean-admin/issues/571 [<samp>(ea8aa)</samp>](https://github.com/honghuangdc/soybean-admin/commit/ea8aa6c)
|
||||||
|
|
||||||
|
### 🐞 Bug 修复
|
||||||
|
|
||||||
|
- **项目**: 修复 vertical-mix 菜单选中问题 - 由 @honghuangdc [<samp>(59f07)</samp>](https://github.com/honghuangdc/soybean-admin/commit/59f07d8)
|
||||||
|
|
||||||
|
### 🛠 优化
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 添加类型 WatermarkProps - 由 @honghuangdc [<samp>(f26d0)</samp>](https://github.com/honghuangdc/soybean-admin/commit/f26d0a6)
|
||||||
|
- 移除 home NAlert 可关闭 - 由 @honghuangdc [<samp>(98b75)</samp>](https://github.com/honghuangdc/soybean-admin/commit/98b75c2)
|
||||||
|
- 优化响应代码比较 - 由 @honghuangdc [<samp>(cf67d)</samp>](https://github.com/honghuangdc/soybean-admin/commit/cf67d55)
|
||||||
|
- **类型**:
|
||||||
|
- 移除无用类型。 - 由 **Azir** [<samp>(eed61)</samp>](https://github.com/honghuangdc/soybean-admin/commit/eed617f)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**: 更新更新日志 - 由 @honghuangdc [<samp>(d3759)</samp>](https://github.com/honghuangdc/soybean-admin/commit/d37591d)
|
||||||
|
|
||||||
|
### 🏡 杂项
|
||||||
|
|
||||||
|
- **依赖**: 更新依赖 - 由 @honghuangdc [<samp>(993e9)</samp>](https://github.com/honghuangdc/soybean-admin/commit/993e9ca)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc) [](https://github.com/paynezhuang) [](https://github.com/Azir-11)
|
||||||
|
[Azir](mailto:2075125282@qq.com),
|
||||||
|
|
||||||
|
## [v1.3.1](https://github.com/honghuangdc/soybean-admin/compare/v1.3.0...v1.3.1) (2024-07-22)
|
||||||
|
|
||||||
|
### 🐞 Bug 修复
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 修复顶部菜单混合和反向模式下侧边栏宽度异常的问题 - 由 @Azir-11 在 https://github.com/honghuangdc/soybean-admin/issues/562 修复 [<samp>(c4695)</samp>](https://github.com/honghuangdc/soybean-admin/commit/c469512)
|
||||||
|
- 修复水平混合菜单反转问题。修复 #563 - 由 @honghuangdc 在 https://github.com/honghuangdc/soybean-admin/issues/563 修复 [<samp>(4e55b)</samp>](https://github.com/honghuangdc/soybean-admin/commit/4e55b0e)
|
||||||
|
- 修复当布局来自移动端时垂直菜单不渲染的问题 - 由 @honghuangdc 修复 [<samp>(84027)</samp>](https://github.com/honghuangdc/soybean-admin/commit/8402734)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**: 更新更新日志 - 由 @honghuangdc 更新 [<samp>(613c8)</samp>](https://github.com/honghuangdc/soybean-admin/commit/613c836)
|
||||||
|
|
||||||
|
### 🎨 样式
|
||||||
|
|
||||||
|
- **其他**: 修改灰度模式的中文名称 - 由 **Azir** 修改 [<samp>(53770)</samp>](https://github.com/honghuangdc/soybean-admin/commit/5377002)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc) [](https://github.com/Azir-11)
|
||||||
|
[Azir](mailto:2075125282@qq.com),
|
||||||
|
|
||||||
|
|
||||||
|
## [v1.3.0](https://github.com/soybeanjs/soybean-admin/compare/v1.2.8...v1.3.0) (2024-07-22)
|
||||||
|
|
||||||
|
### 🚨 破坏性变更
|
||||||
|
|
||||||
|
- **项目**: 重构全局菜单 & 支持 `reversed-horizontal-mix-menu`。关闭 #365 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/365 提出 [<samp>(087e5)</samp>](https://github.com/soybeanjs/soybean-admin/commit/087e532)
|
||||||
|
|
||||||
|
### 🚀 功能
|
||||||
|
|
||||||
|
- **包**:
|
||||||
|
- `@sa/scripts`: 命令 `gitCommit` 支持中文 - 由 @mmdapl 在 https://github.com/soybeanjs/soybean-admin/issues/548 提出 [<samp>(06971)</samp>](https://github.com/soybeanjs/soybean-admin/commit/06971f3)
|
||||||
|
- @sa/axios: 用 AbortController 替换 CancelTokenSource。关闭 #530, 关闭 #532 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/530 和 https://github.com/soybeanjs/soybean-admin/issues/532 提出 [<samp>(527fd)</samp>](https://github.com/soybeanjs/soybean-admin/commit/527fd79)
|
||||||
|
- @sa/scripts: 为命令 `gitCommitVerify` 添加忽略模式列表。关闭 #504 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/504 提出 [<samp>(958d0)</samp>](https://github.com/soybeanjs/soybean-admin/commit/958d0ba)
|
||||||
|
- **项目**:
|
||||||
|
- 使分支 `main` 更精简 & 修改请求重试次数为 0 - 由 @Azir-11 提出 [<samp>(793b1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/793b16e)
|
||||||
|
|
||||||
|
### 🐞 修复
|
||||||
|
|
||||||
|
- **钩子**: 当 pagesize 返回 0 时防止程序冻结 - 由 @Azir-11 在 https://github.com/soybeanjs/soybean-admin/issues/545 提出 [<samp>(f4eeb)</samp>](https://github.com/soybeanjs/soybean-admin/commit/f4eeb2e)
|
||||||
|
|
||||||
|
### 💅 重构
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 合并 `theme tokens` 和 `theme settings`。关闭 #379 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/379 提出 [<samp>(1d1b1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/1d1b148)
|
||||||
|
- 将 css 变量挂载到 root - 由 @honghuangdc 提出 [<samp>(00f41)</samp>](https://github.com/soybeanjs/soybean-admin/commit/00f41dd)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**: 更新更新日志 - 由 @honghuangdc 提出 [<samp>(a0b76)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a0b76da)
|
||||||
|
|
||||||
|
### 🏡 杂务
|
||||||
|
|
||||||
|
- **依赖**: 更新依赖 - 由 @honghuangdc 提出 [<samp>(f6bd6)</samp>](https://github.com/soybeanjs/soybean-admin/commit/f6bd6b8)
|
||||||
|
- **项目**: 添加脚本 `czh` - 由 @honghuangdc 提出 [<samp>(02069)</samp>](https://github.com/soybeanjs/soybean-admin/commit/0206969)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc) [](https://github.com/mmdapl) [](https://github.com/Azir-11)
|
||||||
|
|
||||||
|
|
||||||
|
## [v1.2.8](https://github.com/soybeanjs/soybean-admin/compare/v1.2.7...v1.2.8) (2024-07-20)
|
||||||
|
|
||||||
|
### 🐞 修复
|
||||||
|
|
||||||
|
- **包**:
|
||||||
|
- @sa/hooks: 修复 useHookTable 的 searchParams。修复了 #552 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/552 提出 [<samp>(96c10)</samp>](https://github.com/soybeanjs/soybean-admin/commit/96c1044)
|
||||||
|
- **类型**:
|
||||||
|
- 修复了引用类型错误 - 由 **dodu2014** 在 https://github.com/soybeanjs/soybean-admin/issues/551 提出 [<samp>(3e2a9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3e2a993)
|
||||||
|
- 修复 useHookTable 的数据类型 - 由 @honghuangdc 提出 [<samp>(276ea)</samp>](https://github.com/soybeanjs/soybean-admin/commit/276ea7f)
|
||||||
|
|
||||||
|
### 💅 重构
|
||||||
|
|
||||||
|
- **项目**: 用 `klona` 替换 `lodash-es` 的 `cloneDeep` - 由 @honghuangdc 提出 [<samp>(a9133)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a91335d)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**: 更新更新日志 - 由 @honghuangdc 提出 [<samp>(58fc0)</samp>](https://github.com/soybeanjs/soybean-admin/commit/58fc096)
|
||||||
|
|
||||||
|
### 🏡 杂务
|
||||||
|
|
||||||
|
- **依赖**: 更新依赖 - 由 @honghuangdc 提出 [<samp>(cf019)</samp>](https://github.com/soybeanjs/soybean-admin/commit/cf0192a)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
[dodu2014](mailto:dodu@live.cn)
|
||||||
|
|
||||||
|
|
||||||
|
## [v1.2.7](https://github.com/honghuangdc/soybean-admin/compare/v1.2.6...v1.2.7) (2024-07-12)
|
||||||
|
|
||||||
|
### 🛠 优化
|
||||||
|
|
||||||
|
- **项目**: 支持自定义菜单图标大小 - 由 @wynn-w 在 https://github.com/honghuangdc/soybean-admin/issues/534 提出 [<samp>(e035e)</samp>](https://github.com/honghuangdc/soybean-admin/commit/e035eab)
|
||||||
|
|
||||||
|
### 🏡 杂务
|
||||||
|
|
||||||
|
- **依赖**:
|
||||||
|
- 更新依赖 - 由 @honghuangdc [<samp>(72ede)</samp>](https://github.com/honghuangdc/soybean-admin/commit/72ede8b)
|
||||||
|
- 更新依赖 - 由 @honghuangdc [<samp>(be13c)</samp>](https://github.com/honghuangdc/soybean-admin/commit/be13ca2)
|
||||||
|
- 更新依赖 - 由 @honghuangdc [<samp>(752ec)</samp>](https://github.com/honghuangdc/soybean-admin/commit/752ec1e)
|
||||||
|
- **项目**:
|
||||||
|
- 修复已弃用的配置配置 - 由 @paynezhuang 在 https://github.com/honghuangdc/soybean-admin/issues/524 提出 [<samp>(0d20e)</samp>](https://github.com/honghuangdc/soybean-admin/commit/0d20e4c)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc) [](https://github.com/wynn-w) [](https://github.com/paynezhuang)
|
||||||
|
|
||||||
|
## [v1.2.6](https://github.com/honghuangdc/soybean-admin/compare/v1.2.5...v1.2.6) (2024-06-21)
|
||||||
|
|
||||||
|
### 🐞 修复
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 请求模态标题使用 i18n。修复 #507 - 由 @honghuangdc 在 https://github.com/honghuangdc/soybean-admin/issues/507 提出 [<samp>(f7de3)</samp>](https://github.com/honghuangdc/soybean-admin/commit/f7de3fd)
|
||||||
|
- 为 `useTable` 添加 `getDataByPage`。修复 #499 - 由 @honghuangdc 在 https://github.com/honghuangdc/soybean-admin/issues/499 提出 [<samp>(425c6)</samp>](https://github.com/honghuangdc/soybean-admin/commit/425c69a)
|
||||||
|
- 修复登录重定向到 routeHome 时,动态路由的 routeHome 与静态路由不同的问题。修复 #511 - 由 @honghuangdc 在 https://github.com/honghuangdc/soybean-admin/issues/511 提出 [<samp>(49f60)</samp>](https://github.com/honghuangdc/soybean-admin/commit/49f60b2)
|
||||||
|
|
||||||
|
### 🛠 优化
|
||||||
|
|
||||||
|
- **项目**: 优化 `getRouteQueryOfLoginRoute` - 由 @honghuangdc [<samp>(693f7)</samp>](https://github.com/honghuangdc/soybean-admin/commit/693f704)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 更新更新日志 - 由 @honghuangdc [<samp>(5c67d)</samp>](https://github.com/honghuangdc/soybean-admin/commit/5c67d06)
|
||||||
|
- 更新自述文件 - 由 @honghuangdc [<samp>(1e67a)</samp>](https://github.com/honghuangdc/soybean-admin/commit/1e67ae8)
|
||||||
|
|
||||||
|
### 🏡 杂务
|
||||||
|
|
||||||
|
- **依赖**:
|
||||||
|
- 更新依赖。关闭 #510 - 由 @honghuangdc 在 https://github.com/honghuangdc/soybean-admin/issues/510 提出 [<samp>(53143)</samp>](https://github.com/honghuangdc/soybean-admin/commit/531432d)
|
||||||
|
- 更新依赖 - 由 @honghuangdc [<samp>(c7f6f)</samp>](https://github.com/honghuangdc/soybean-admin/commit/c7f6f2a)
|
||||||
|
|
||||||
|
### 🤖 CI
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 添加 github 问题模板 - 由 @honghuangdc [<samp>(b5027)</samp>](https://github.com/honghuangdc/soybean-admin/commit/b5027c8)
|
||||||
|
- 更新 github 问题模板 - 由 @honghuangdc [<samp>(ff1d5)</samp>](https://github.com/honghuangdc/soybean-admin/commit/ff1d504)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
|
||||||
|
## [v1.2.5](https://github.com/soybeanjs/soybean-admin/compare/v1.2.4...v1.2.5) (2024-06-15)
|
||||||
|
|
||||||
|
### 🐞 错误修复
|
||||||
|
|
||||||
|
- **项目**: 修复登出后标签页异常缓存的问题。已修复 #495 - 由 @Azir-11 在 https://github.com/soybeanjs/soybean-admin/issues/495 [<samp>(3eeac)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3eeace9)
|
||||||
|
|
||||||
|
### 🔥 性能
|
||||||
|
|
||||||
|
- **项目**: 初始化静态路由功能不需要异步 - 由 **CHENZL** 在 https://github.com/soybeanjs/soybean-admin/issues/493 [<samp>(2198b)</samp>](https://github.com/soybeanjs/soybean-admin/commit/2198b98)
|
||||||
|
|
||||||
|
### 🛠 优化
|
||||||
|
|
||||||
|
- **项目**: 优化代码 - 由 @soybeanjs [<samp>(b94ba)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b94baa1)
|
||||||
|
- **类型**: 提高全局类型的兼容性 - 由 @Azir-11 在 https://github.com/soybeanjs/soybean-admin/issues/494 [<samp>(cd9d5)</samp>](https://github.com/soybeanjs/soybean-admin/commit/cd9d58d)
|
||||||
|
- **工具**: 减少代码缩进,提高可读性 - 由 @Azir-11 在 https://github.com/soybeanjs/soybean-admin/issues/496 [<samp>(ad2f2)</samp>](https://github.com/soybeanjs/soybean-admin/commit/ad2f247)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**: 更新CHANGELOG - 由 @soybeanjs [<samp>(f70d2)</samp>](https://github.com/soybeanjs/soybean-admin/commit/f70d29b)
|
||||||
|
|
||||||
|
### 🏡 杂项
|
||||||
|
|
||||||
|
- **依赖**: 更新依赖 - 由 @soybeanjs [<samp>(b094d)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b094d68)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/soybeanjs) [](https://github.com/Azir-11)
|
||||||
|
[CHENZL](mailto:zlong5568863@qq.com)
|
||||||
|
|
||||||
|
|
||||||
|
## [v1.2.4](https://github.com/soybeanjs/soybean-admin/compare/v1.2.3...v1.2.4) (2024-06-14)
|
||||||
|
|
||||||
|
### 🛠 优化
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 优化 `setupAppVersionNotification` - 由 @soybeanjs 提交 [<samp>(b5a72)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b5a723c)
|
||||||
|
- 获取 'Asia/Shanghai' 时区的构建时间 - 由 @soybeanjs 提交 [<samp>(069fa)</samp>](https://github.com/soybeanjs/soybean-admin/commit/069fa8a)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/soybeanjs)
|
||||||
|
|
||||||
|
## [v1.2.3](https://github.com/soybeanjs/soybean-admin/compare/v1.2.2...v1.2.3) (2024-06-13)
|
||||||
|
|
||||||
|
### 🐞 修复错误
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 通过在index.html中添加color-scheme元标签修复移动浏览器主题问题 - 由 @KickCashew 在 https://github.com/soybeanjs/soybean-admin/issues/488 中提交 [<samp>(c2125)</samp>](https://github.com/soybeanjs/soybean-admin/commit/c212565)
|
||||||
|
- 修复二级目录组件为空 - 由 @paynezhuang 在 https://github.com/soybeanjs/soybean-admin/issues/491 中提交 [<samp>(aabb2)</samp>](https://github.com/soybeanjs/soybean-admin/commit/aabb2a4)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 修复超链接指向错误 - 由 **Azir** 提交 [<samp>(20a81)</samp>](https://github.com/soybeanjs/soybean-admin/commit/20a8127)
|
||||||
|
- 更新 README - 由 @soybeanjs 提交 [<samp>(70261)</samp>](https://github.com/soybeanjs/soybean-admin/commit/7026126)
|
||||||
|
|
||||||
|
### 🏡 杂项
|
||||||
|
|
||||||
|
- **依赖**:
|
||||||
|
- 更新依赖 - 由 @soybeanjs 提交 [<samp>(813d8)</samp>](https://github.com/soybeanjs/soybean-admin/commit/813d8ce)
|
||||||
|
- 更新依赖 - 由 @soybeanjs 提交 [<samp>(bf718)</samp>](https://github.com/soybeanjs/soybean-admin/commit/bf71837)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/soybeanjs) [](https://github.com/paynezhuang) [](https://github.com/KickCashew)
|
||||||
|
[Azir](mailto:2075125282@qq.com)
|
||||||
|
|
||||||
|
## [v1.2.2](https://github.com/honghuangdc/soybean-admin/compare/v1.2.1...v1.2.2) (2024-06-12)
|
||||||
|
|
||||||
|
### 🚀 特性
|
||||||
|
|
||||||
|
- **项目**: 切换标签时重置滚动位置 - 由 @soybeanjs 提交 [<samp>(9094b)</samp>](https://github.com/honghuangdc/soybean-admin/commit/9094b21)
|
||||||
|
|
||||||
|
### 🐞 修复错误
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 在DEV模式下隐藏AppVersionNotification - 由 @sigma-plus 在 https://github.com/honghuangdc/soybean-admin/issues/482 中提交 [<samp>(62592)</samp>](https://github.com/honghuangdc/soybean-admin/commit/6259287)
|
||||||
|
- 修复在移动布局中隐藏menu-toggler。fixed #483 - 由 @soybeanjs 在 https://github.com/honghuangdc/soybean-admin/issues/483 中提交 [<samp>(4470c)</samp>](https://github.com/honghuangdc/soybean-admin/commit/4470cb4)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**: 更新 README - 由 @soybeanjs 提交 [<samp>(8f9a7)</samp>](https://github.com/honghuangdc/soybean-admin/commit/8f9a705)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/soybeanjs) [](https://github.com/sigma-plus)
|
||||||
|
|
||||||
|
## [v1.2.1](https://github.com/honghuangdc/soybean-admin/compare/v1.2.0...v1.2.1) (2024-06-07)
|
||||||
|
|
||||||
|
### 🐞 修复错误
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 修复页面重新加载时获取用户信息 - 由 @soybeanjs 提交 [<samp>(ff51b)</samp>](https://github.com/honghuangdc/soybean-admin/commit/ff51b72)
|
||||||
|
- 修复setupAppVersionNotification渲染 - 由 @soybeanjs 提交 [<samp>(6a6eb)</samp>](https://github.com/honghuangdc/soybean-admin/commit/6a6eb9a)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**: 更新CHANGELOG - 由 @soybeanjs [<samp>(fe06b)</samp>](https://github.com/honghuangdc/soybean-admin/commit/fe06b8c)完成
|
||||||
|
|
||||||
|
### 🏡 日常任务
|
||||||
|
|
||||||
|
- **依赖**: 更新依赖 - 由 @soybeanjs [<samp>(08827)</samp>](https://github.com/honghuangdc/soybean-admin/commit/08827a4)完成
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/soybeanjs)
|
||||||
|
|
||||||
|
|
||||||
|
## [v1.2.0](https://github.com/soybeanjs/soybean-admin/compare/v1.1.5...v1.2.0) (2024-06-06)
|
||||||
|
|
||||||
|
### 🚀 功能
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 支持系统新版本更新通知。关闭 #420 - 由 @soybeanjs 在 https://github.com/soybeanjs/soybean-admin/issues/420 [<samp>(584cd)</samp>](https://github.com/soybeanjs/soybean-admin/commit/584cd54)
|
||||||
|
- 在路由守卫中获取用户信息并从localStorage中移除。关闭 #459 - 由 @soybeanjs 在 https://github.com/soybeanjs/soybean-admin/issues/459 [<samp>(5531a)</samp>](https://github.com/soybeanjs/soybean-admin/commit/5531a68)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**: 更新CHANGELOG - 由 @soybeanjs [<samp>(2bec8)</samp>](https://github.com/soybeanjs/soybean-admin/commit/2bec899)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/soybeanjs)
|
||||||
|
|
||||||
|
## [v1.1.5](https://github.com/soybeanjs/soybean-admin/compare/v1.1.4...v1.1.5) (2024-06-06)
|
||||||
|
|
||||||
|
### 🐞 错误修复
|
||||||
|
|
||||||
|
- **项目**: 修复注册组件名,CodeLogin => Register - 由 @m-xlsea 在 https://github.com/soybeanjs/soybean-admin/issues/478 [<samp>(ddf38)</samp>](https://github.com/soybeanjs/soybean-admin/commit/ddf3823)
|
||||||
|
|
||||||
|
### 🏡 杂务
|
||||||
|
|
||||||
|
- **依赖**: 更新依赖 - 由 @soybeanjs [<samp>(060c0)</samp>](https://github.com/soybeanjs/soybean-admin/commit/060c0a9)
|
||||||
|
- **项目**: 更新 vscode 设置: vue 官方 - 由 @soybeanjs [<samp>(76649)</samp>](https://github.com/soybeanjs/soybean-admin/commit/76649e2)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/soybeanjs) [](https://github.com/m-xlsea)
|
||||||
|
|
||||||
|
## [v1.1.4](https://github.com/honghuangdc/soybean-admin/compare/v1.1.3...v1.1.4) (2024-06-06)
|
||||||
|
|
||||||
|
### 🐞 错误修复
|
||||||
|
|
||||||
|
- **utils**: 修复了按esc键时modalLogout的错误 - 由 @sigma-plus 在 https://github.com/honghuangdc/soybean-admin/issues/470 中提出 [<samp>(bd69c)</samp>](https://github.com/honghuangdc/soybean-admin/commit/bd69c00)
|
||||||
|
|
||||||
|
### 🛠 优化
|
||||||
|
|
||||||
|
- **projects**: 优化了RouteMeta的备注 - 由 @soybeanjs 提出 [<samp>(ffb48)</samp>](https://github.com/honghuangdc/soybean-admin/commit/ffb48b1)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **projects**:
|
||||||
|
- 更新了CHANGELOG - 由 @soybeanjs 提出 [<samp>(756f8)</samp>](https://github.com/honghuangdc/soybean-admin/commit/756f84a)
|
||||||
|
- 更新了Node&pnpm版本 - 由 @Azir-11 在 https://github.com/honghuangdc/soybean-admin/issues/472 中提出 [<samp>(9b05d)</samp>](https://github.com/honghuangdc/soybean-admin/commit/9b05d73)
|
||||||
|
|
||||||
|
### 🏡 杂项
|
||||||
|
|
||||||
|
- **deps**:
|
||||||
|
- 更新了依赖 - 由 @soybeanjs 提出 [<samp>(d0380)</samp>](https://github.com/honghuangdc/soybean-admin/commit/d0380ce)
|
||||||
|
- 更新了依赖 - 由 @soybeanjs 提出 [<samp>(1f464)</samp>](https://github.com/honghuangdc/soybean-admin/commit/1f4647b)
|
||||||
|
- **projects**:
|
||||||
|
- 关闭了http代理 - 由 @soybeanjs 提出 [<samp>(d08a3)</samp>](https://github.com/honghuangdc/soybean-admin/commit/d08a381)
|
||||||
|
- 更新了mock url - 由 @soybeanjs 提出 [<samp>(e6086)</samp>](https://github.com/honghuangdc/soybean-admin/commit/e6086f0)
|
||||||
|
- 更新了vscode设置 - 由 @soybeanjs 提出 [<samp>(910df)</samp>](https://github.com/honghuangdc/soybean-admin/commit/910dfca)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/soybeanjs) [](https://github.com/Azir-11) [](https://github.com/sigma-plus)
|
||||||
|
|
||||||
|
## [v1.1.3](https://github.com/soybeanjs/soybean-admin/compare/v1.1.2...v1.1.3) (2024-06-02)
|
||||||
|
|
||||||
|
### 🐞 错误修复
|
||||||
|
|
||||||
|
- **组件**:
|
||||||
|
- 修复了由于回车导致搜索框反复弹出的问题 - 由 @Azir-11 在 https://github.com/soybeanjs/soybean-admin/issues/468 中修复 [<samp>(5bd96)</samp>](https://github.com/soybeanjs/soybean-admin/commit/5bd96b8)
|
||||||
|
- **项目**:
|
||||||
|
- 修复点击菜单搜索。修复了 #466,关闭 #467 - 由 @soybeanjs 在 https://github.com/soybeanjs/soybean-admin/issues/466 和 https://github.com/soybeanjs/soybean-admin/issues/467 中修复 [<samp>(8efdb)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8efdb10)
|
||||||
|
- 修复 reCacheRoute。修复了 #464 - 由 @soybeanjs 在 https://github.com/soybeanjs/soybean-admin/issues/464 中修复 [<samp>(59faf)</samp>](https://github.com/soybeanjs/soybean-admin/commit/59faf15)
|
||||||
|
- **样式**:
|
||||||
|
- 修复 FirstLevelMenu 样式。修复了 #450 - 由 @soybeanjs 在 https://github.com/soybeanjs/soybean-admin/issues/450 中修复 [<samp>(db64b)</samp>](https://github.com/soybeanjs/soybean-admin/commit/db64b0e)
|
||||||
|
- 修复 PinToggler 样式。修复了 #451 - 由 @soybeanjs 在 https://github.com/soybeanjs/soybean-admin/issues/451 中修复 [<samp>(42b12)</samp>](https://github.com/soybeanjs/soybean-admin/commit/42b121a)
|
||||||
|
|
||||||
|
### 🛠 优化
|
||||||
|
|
||||||
|
- **组件**: 提高 TableColumnSetting 的拖动区域精度,带有动画 - 由 @orangelckc 在 https://github.com/soybeanjs/soybean-admin/issues/465 中优化 [<samp>(2aa85)</samp>](https://github.com/soybeanjs/soybean-admin/commit/2aa85c6)
|
||||||
|
- **项目**: unocss 边框快捷方式 - 由 @soybeanjs 优化 [<samp>(40d0f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/40d0f8a)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**: 更新 CHANGELOG - 由 @soybeanjs 更新 [<samp>(87b18)</samp>](https://github.com/soybeanjs/soybean-admin/commit/87b1838)
|
||||||
|
|
||||||
|
### 🏡 杂项
|
||||||
|
|
||||||
|
- **其他**:
|
||||||
|
- 纠正拼写错误 - 由 @orangelckc 在 https://github.com/soybeanjs/soybean-admin/issues/460 中纠正 [<samp>(086ba)</samp>](https://github.com/soybeanjs/soybean-admin/commit/086bad4)
|
||||||
|
- 纠正拼写错误 - 由 @Azir-11 在 https://github.com/soybeanjs/soybean-admin/issues/462 中纠正 [<samp>(f1850)</samp>](https://github.com/soybeanjs/soybean-admin/commit/f185041)
|
||||||
|
- **项目**:
|
||||||
|
- 更新 vscode launch.json - 由 @soybeanjs 更新 [<samp>(4c1c7)</samp>](https://github.com/soybeanjs/soybean-admin/commit/4c1c7e6)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/soybeanjs) [](https://github.com/Azir-11) [](https://github.com/orangelckc)
|
||||||
|
|
||||||
|
## [v1.1.2](https://github.com/soybeanjs/soybean-admin/compare/v1.1.1...v1.1.2) (2024-05-24)
|
||||||
|
|
||||||
|
### 🐞 错误修复
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 修复头部样式 & 修复点击全局标签时按钮高亮。修复了 #446 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/446 [<samp>(64fc0)</samp>](https://github.com/soybeanjs/soybean-admin/commit/64fc099)
|
||||||
|
- 修复多标签页只渲染一次。修复了 #441 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/441 [<samp>(e379d)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e379d6c)
|
||||||
|
|
||||||
|
### 🛠 优化
|
||||||
|
|
||||||
|
- **项目**: 优化代码 - 由 @honghuangdc [<samp>(bc8dc)</samp>](https://github.com/soybeanjs/soybean-admin/commit/bc8dc47)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
|
||||||
|
## [v1.1.1](https://github.com/soybeanjs/soybean-admin/compare/v1.1.0...v1.1.1) (2024-05-20)
|
||||||
|
|
||||||
|
### 🚀 功能
|
||||||
|
|
||||||
|
- **hooks**: 为 useEcharts 添加 setOptions - 由 @honghuangdc 提交 [<samp>(e4d53)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e4d53aa)
|
||||||
|
|
||||||
|
### 🐞 修复错误
|
||||||
|
|
||||||
|
- **projects**:
|
||||||
|
- 修复 useRouter。修复了 #436 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/436 提交 [<samp>(0774a)</samp>](https://github.com/soybeanjs/soybean-admin/commit/0774a51)
|
||||||
|
- 在动态路由模式下获取路由时添加错误处理。修复了 440 - 由 @honghuangdc 提交 [<samp>(57b4a)</samp>](https://github.com/soybeanjs/soybean-admin/commit/57b4a9d)
|
||||||
|
- **styles**:
|
||||||
|
- 修复 useTable 类型 - 由 @honghuangdc 提交 [<samp>(07124)</samp>](https://github.com/soybeanjs/soybean-admin/commit/071241f)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **projects**:
|
||||||
|
- 更新 CHANGELOG - 由 @honghuangdc 提交 [<samp>(19783)</samp>](https://github.com/soybeanjs/soybean-admin/commit/1978397)
|
||||||
|
- 更新 README.md - 由 @honghuangdc 提交 [<samp>(fa56e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/fa56e9c)
|
||||||
|
- 更新 README.md - 由 @honghuangdc 提交 [<samp>(419ea)</samp>](https://github.com/soybeanjs/soybean-admin/commit/419ea42)
|
||||||
|
|
||||||
|
### 🏡 杂项
|
||||||
|
|
||||||
|
- **projects**:
|
||||||
|
- 更新依赖并修复 TS 错误 - 由 @honghuangdc 提交 [<samp>(4ea9c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/4ea9c85)
|
||||||
|
- 更新 eslint-config 并修复代码 - 由 @honghuangdc 提交 [<samp>(68ea9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/68ea974)
|
||||||
|
- 更新 @elegant-router/vue 并为 resolve route 添加错误处理。修复了 #442 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/442 提交 [<samp>(24ff8)</samp>](https://github.com/soybeanjs/soybean-admin/commit/24ff852)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
|
||||||
|
## [v1.1.0](https://github.com/honghuangdc/soybean-admin/compare/v1.0.9...v1.1.0) (2024-05-07)
|
||||||
|
|
||||||
|
### 🚀 功能
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 支持灰度。修复了 #385 - 由 @honghuangdc 在 https://github.com/honghuangdc/soybean-admin/issues/385 [<samp>(d335d)</samp>](https://github.com/honghuangdc/soybean-admin/commit/d335df6)
|
||||||
|
- 添加前缀到本地存储 - 由 **Azir** [<samp>(1fc34)</samp>](https://github.com/honghuangdc/soybean-admin/commit/1fc34cc)
|
||||||
|
- 添加表格显示总数选项 - 由 **paynezhuang** [<samp>(3e61e)</samp>](https://github.com/honghuangdc/soybean-admin/commit/3e61eab)
|
||||||
|
- 添加推荐颜色切换。关闭了 #388 - 由 @honghuangdc 在 https://github.com/honghuangdc/soybean-admin/issues/388 [<samp>(a1920)</samp>](https://github.com/honghuangdc/soybean-admin/commit/a1920fc)
|
||||||
|
- 添加菜单路由字段 - 由 **paynezhuang** [<samp>(dbe31)</samp>](https://github.com/honghuangdc/soybean-admin/commit/dbe31eb)
|
||||||
|
- 支持短时间内重复请求错误只出现一次。关闭了 #368, 关闭了 #369 - 由 @honghuangdc 在 https://github.com/honghuangdc/soybean-admin/issues/368 和 https://github.com/honghuangdc/soybean-admin/issues/369 [<samp>(e3bd3)</samp>](https://github.com/honghuangdc/soybean-admin/commit/e3bd397)
|
||||||
|
- 通过鼠标滚轮按钮点击关闭标签 - 由 **JianJroh** [<samp>(d3849)</samp>](https://github.com/honghuangdc/soybean-admin/commit/d3849ba)
|
||||||
|
- 页面:支持管理菜单更多选项。关闭了 #366 - 由 @honghuangdc 在 https://github.com/honghuangdc/soybean-admin/issues/366 [<samp>(c4b5c)</samp>](https://github.com/honghuangdc/soybean-admin/commit/c4b5c65)
|
||||||
|
- useTable 添加展开显示 - 由 **paynezhuang** [<samp>(0a90d)</samp>](https://github.com/honghuangdc/soybean-admin/commit/0a90dd3)
|
||||||
|
|
||||||
|
### 🐞 错误修复
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 菜单 fixedIndexInTab 默认为 null - 由 **paynezhuang** [<samp>(3d10e)</samp>](https://github.com/honghuangdc/soybean-admin/commit/3d10ef1)
|
||||||
|
- 修复菜单切换器 zIndex - 由 @honghuangdc [<samp>(7bd43)</samp>](https://github.com/honghuangdc/soybean-admin/commit/7bd43df)
|
||||||
|
- 修复管理菜单模态样式 - 由 @honghuangdc [<samp>(60f3b)</samp>](https://github.com/honghuangdc/soybean-admin/commit/60f3b14)
|
||||||
|
- 当角色改变时修复菜单数据。修复了 #391 - 由 @honghuangdc 在 https://github.com/honghuangdc/soybean-admin/issues/391 [<samp>(3b47b)</samp>](https://github.com/honghuangdc/soybean-admin/commit/3b47b5a)
|
||||||
|
|
||||||
|
### 🛠 优化
|
||||||
|
|
||||||
|
- **项目**: 移除废弃的代码 - 由 @honghuangdc [<samp>(72ccb)</samp>](https://github.com/honghuangdc/soybean-admin/commit/72ccb6b)
|
||||||
|
|
||||||
|
### 💅 重构
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 重构 @sa/color-palette => @sa/color & 优化 @sa/utils 代码 - 由 @honghuangdc [<samp>(34999)</samp>](https://github.com/honghuangdc/soybean-admin/commit/3499997)
|
||||||
|
- menu-operate-drawer => menu-operate-modal - 由 @honghuangdc [<samp>(003e1)</samp>](https://github.com/honghuangdc/soybean-admin/commit/003e145)
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 添加 CHANGELOG.zh_CN.md - 由 @honghuangdc [<samp>(18b3f)</samp>](https://github.com/honghuangdc/soybean-admin/commit/18b3f05)
|
||||||
|
- 更新 CHANGELOG - 由 @honghuangdc [<samp>(4d17c)</samp>](https://github.com/honghuangdc/soybean-admin/commit/4d17cfd)
|
||||||
|
|
||||||
|
### 🏡 杂项
|
||||||
|
|
||||||
|
- **依赖**:
|
||||||
|
- 更新依赖 - 由 @honghuangdc [<samp>(1cb38)</samp>](https://github.com/honghuangdc/soybean-admin/commit/1cb3816)
|
||||||
|
- 更新依赖 - 由 @honghuangdc [<samp>(599b4)</samp>](https://github.com/honghuangdc/soybean-admin/commit/599b4e1)
|
||||||
|
- **项目**:
|
||||||
|
- 合并 main 到 v1.1.0 - 由 @honghuangdc [<samp>(ebe55)</samp>](https://github.com/honghuangdc/soybean-admin/commit/ebe55af)
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
[paynezhuang](mailto:paynezhuang@gmail.com), [JianJroh](mailto:rhjian@foxmail.com), [Azir](mailto:2075125282@qq.com)
|
||||||
|
|
||||||
|
## [v1.1.0-beta.2](https://github.com/honghuangdc/soybean-admin/compare/v1.1.0-beta.1...v1.1.0-beta.2) (2024-05-07)
|
||||||
|
|
||||||
|
### 🚀 特性
|
||||||
|
|
||||||
|
- **项目**: useTable添加展开以显示 - 由 **paynezhuang** [<samp>(0a90d)</samp>](https://github.com/honghuangdc/soybean-admin/commit/0a90dd3) 提供
|
||||||
|
|
||||||
|
### 🐞 修复的错误
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 修复 manage_menu 模态样式 - 由 @honghuangdc [<samp>(60f3b)</samp>](https://github.com/honghuangdc/soybean-admin/commit/60f3b14) 提供
|
||||||
|
- 当角色改变时修复菜单数据。修复了 #391 - 由 @honghuangdc 在 https://github.com/honghuangdc/soybean-admin/issues/391 [<samp>(3b47b)</samp>](https://github.com/honghuangdc/soybean-admin/commit/3b47b5a) 提供
|
||||||
|
|
||||||
|
### 🛠 优化
|
||||||
|
|
||||||
|
- **项目**: 删除废弃的代码 - 由 @honghuangdc [<samp>(72ccb)</samp>](https://github.com/honghuangdc/soybean-admin/commit/72ccb6b) 提供
|
||||||
|
|
||||||
|
### 📖 文档
|
||||||
|
|
||||||
|
- **项目**: 添加 CHANGELOG.zh_CN.md - 由 @honghuangdc [<samp>(18b3f)</samp>](https://github.com/honghuangdc/soybean-admin/commit/18b3f05) 提供
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
[paynezhuang](mailto:paynezhuang@gmail.com)
|
||||||
|
|
||||||
|
|
||||||
|
## [v1.1.0-beta.1](https://github.com/soybeanjs/soybean-admin/compare/v1.0.9...v1.1.0-beta.1) (2024-05-07)
|
||||||
|
|
||||||
|
### 🚀 功能
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 支持灰度。修复了 #385 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/385 [<samp>(d335d)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d335df6)
|
||||||
|
- 添加前缀到本地存储 - 由 **Azir** [<samp>(1fc34)</samp>](https://github.com/soybeanjs/soybean-admin/commit/1fc34cc)
|
||||||
|
- 添加表格 showTotal 选项 - 由 **paynezhuang** [<samp>(3e61e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3e61eab)
|
||||||
|
- 添加推荐颜色切换。关闭了 #388 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/388 [<samp>(a1920)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a1920fc)
|
||||||
|
- 添加菜单路由字段 - 由 **paynezhuang** [<samp>(dbe31)</samp>](https://github.com/soybeanjs/soybean-admin/commit/dbe31eb)
|
||||||
|
- 支持短时间内重复请求错误只发生一次。关闭了 #368, 关闭了 #369 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/368 和 https://github.com/soybeanjs/soybean-admin/issues/369 [<samp>(e3bd3)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e3bd397)
|
||||||
|
- 通过鼠标滚轮按钮点击关闭标签 - 由 **JianJroh** [<samp>(d3849)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d3849ba)
|
||||||
|
- 页面:支持更多的 manage_menu 选项。关闭了 #366 - 由 @honghuangdc 在 https://github.com/soybeanjs/soybean-admin/issues/366 [<samp>(c4b5c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/c4b5c65)
|
||||||
|
|
||||||
|
### 🐞 错误修复
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 修复菜单 fixedIndexInTab 默认为 null - 由 **paynezhuang** [<samp>(3d10e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3d10ef1)完成
|
||||||
|
- 修复菜单切换器 zIndex - 由 @honghuangdc [<samp>(7bd43)</samp>](https://github.com/soybeanjs/soybean-admin/commit/7bd43df)完成
|
||||||
|
|
||||||
|
### 💅 重构
|
||||||
|
|
||||||
|
- **项目**:
|
||||||
|
- 重构 @sa/color-palette => @sa/color & 性能优化 @sa/utils - 由 @honghuangdc [<samp>(34999)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3499997)完成
|
||||||
|
- menu-operate-drawer => menu-operate-modal - 由 @honghuangdc [<samp>(003e1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/003e145)完成
|
||||||
|
|
||||||
|
### 🏡 杂务
|
||||||
|
|
||||||
|
- **依赖**:
|
||||||
|
- 更新依赖 - 由 @honghuangdc [<samp>(1cb38)</samp>](https://github.com/soybeanjs/soybean-admin/commit/1cb3816)完成
|
||||||
|
- 更新依赖 - 由 @honghuangdc [<samp>(599b4)</samp>](https://github.com/soybeanjs/soybean-admin/commit/599b4e1)完成
|
||||||
|
- **项目**:
|
||||||
|
- 合并主分支到 v1.1.0 - 由 @honghuangdc [<samp>(ebe55)</samp>](https://github.com/soybeanjs/soybean-admin/commit/ebe55af)完成
|
||||||
|
|
||||||
|
### ❤️ 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
[JianJroh](mailto:rhjian@foxmail.com), [paynezhuang](mailto:paynezhuang@gmail.com), [Azir](mailto:2075125282@qq.com)
|
||||||
42
EXECUTE_THIS_FIX.sql
Normal file
42
EXECUTE_THIS_FIX.sql
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
-- ========================================
|
||||||
|
-- 执行此 SQL 脚本来修复组件路径问题
|
||||||
|
-- ========================================
|
||||||
|
-- 问题说明:
|
||||||
|
-- 1. 路由名称(name)使用下划线:user_manage, my_device
|
||||||
|
-- 2. 但组件路径(component)必须使用连字符匹配实际文件夹:user-manage, my-device
|
||||||
|
-- 3. 之前的路由名称修复导致 component 路径不匹配,引发前端错误
|
||||||
|
-- ========================================
|
||||||
|
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
-- 修复 user-manage 相关组件(文件夹是 user-manage)
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.user-manage' WHERE name = 'user_manage';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.user-manage_list' WHERE name = 'user_manage_list';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.user-manage_role' WHERE name = 'user_manage_role';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.user-manage_permission' WHERE name = 'user_manage_permission';
|
||||||
|
|
||||||
|
-- 修复 my-device 相关组件(文件夹是 my-device)
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-device' WHERE name = 'my_device';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-device_status' WHERE name = 'my_device_status';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-device_power-control' WHERE name = 'my_device_power';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-device_remote-control' WHERE name = 'my_device_remote';
|
||||||
|
|
||||||
|
-- 修复 my-application 相关组件(文件夹是 my-application)
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-application' WHERE name = 'my_application';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-application_apply' WHERE name = 'my_application_apply';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-application_my-list' WHERE name = 'my_application_list';
|
||||||
|
|
||||||
|
-- 验证修复结果
|
||||||
|
SELECT
|
||||||
|
name AS '路由名称(下划线)',
|
||||||
|
path AS '路径',
|
||||||
|
component AS '组件路径(连字符)'
|
||||||
|
FROM sys_route
|
||||||
|
WHERE name LIKE '%user%' OR name LIKE '%my_%'
|
||||||
|
ORDER BY name;
|
||||||
|
|
||||||
|
-- 预期结果示例:
|
||||||
|
-- user_manage | /user-manage | layout.base$view.user-manage
|
||||||
|
-- user_manage_list | /user-manage/list | layout.base$view.user-manage_list
|
||||||
|
-- my_device | /my-device | layout.base$view.my-device
|
||||||
|
-- my_device_status | /my-device/status | layout.base$view.my-device_status
|
||||||
33
FINAL_FIX_ALL.bat
Normal file
33
FINAL_FIX_ALL.bat
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo 最终完整修复所有路由问题
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 此脚本将:
|
||||||
|
echo 1. 修复所有路由名称(与前端 routeMap 一致)
|
||||||
|
echo 2. 修复所有组件路径
|
||||||
|
echo 3. 更新所有角色的菜单配置
|
||||||
|
echo 4. 验证修复结果
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
|
||||||
|
mysql -u root -proot < FINAL_FIX_ALL.sql
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 修复完成!请查看上面的验证结果
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 重要提示:
|
||||||
|
echo 1. 检查"用户管理路由配置"是否正确
|
||||||
|
echo 2. 检查"检查子路由是否在角色配置中"全部显示 YES
|
||||||
|
echo 3. 如果全部正确,重启后端服务
|
||||||
|
echo 4. 清除浏览器缓存(Ctrl+Shift+Delete)
|
||||||
|
echo 5. 刷新浏览器(Ctrl+F5)
|
||||||
|
echo.
|
||||||
|
echo 如果用户管理还是显示为按钮:
|
||||||
|
echo - 查看后端控制台日志
|
||||||
|
echo - 搜索"路由: user-manage_list - 是否允许"
|
||||||
|
echo - 如果显示 false,说明角色配置还有问题
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
145
FINAL_FIX_ALL.sql
Normal file
145
FINAL_FIX_ALL.sql
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
-- 最终完整修复所有路由问题
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 第一步:修复所有路由的 name 字段
|
||||||
|
-- 必须与前端 routeMap 完全一致
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- 设备管理
|
||||||
|
UPDATE sys_route SET name = 'device' WHERE route_id = 'device';
|
||||||
|
UPDATE sys_route SET name = 'device_list' WHERE route_id = 'device_list';
|
||||||
|
UPDATE sys_route SET name = 'device_online' WHERE route_id = 'device_online';
|
||||||
|
UPDATE sys_route SET name = 'device_power' WHERE route_id = 'device_power';
|
||||||
|
UPDATE sys_route SET name = 'device_monitor' WHERE route_id = 'device_monitor';
|
||||||
|
UPDATE sys_route SET name = 'device_group' WHERE route_id = 'device_group';
|
||||||
|
|
||||||
|
-- 屏幕监控
|
||||||
|
UPDATE sys_route SET name = 'screen' WHERE route_id = 'screen';
|
||||||
|
UPDATE sys_route SET name = 'screen_wall' WHERE route_id = 'screen_wall';
|
||||||
|
UPDATE sys_route SET name = 'screen_control' WHERE route_id = 'screen_control';
|
||||||
|
UPDATE sys_route SET name = 'screen_record' WHERE route_id = 'screen_record';
|
||||||
|
|
||||||
|
-- 用户管理(关键!)
|
||||||
|
UPDATE sys_route SET name = 'user-manage' WHERE route_id = 'user_manage';
|
||||||
|
UPDATE sys_route SET name = 'user-manage_list' WHERE route_id = 'user_list';
|
||||||
|
UPDATE sys_route SET name = 'user-manage_role' WHERE route_id = 'user_role';
|
||||||
|
UPDATE sys_route SET name = 'user-manage_permission' WHERE route_id = 'user_permission';
|
||||||
|
|
||||||
|
-- 申请管理
|
||||||
|
UPDATE sys_route SET name = 'application' WHERE route_id = 'application';
|
||||||
|
UPDATE sys_route SET name = 'application_approval' WHERE route_id = 'application_approval';
|
||||||
|
UPDATE sys_route SET name = 'application_history' WHERE route_id = 'application_history';
|
||||||
|
|
||||||
|
-- 系统设置
|
||||||
|
UPDATE sys_route SET name = 'system' WHERE route_id = 'system';
|
||||||
|
UPDATE sys_route SET name = 'system_amt' WHERE route_id = 'system_amt';
|
||||||
|
UPDATE sys_route SET name = 'system_agent' WHERE route_id = 'system_agent';
|
||||||
|
UPDATE sys_route SET name = 'system_log' WHERE route_id = 'system_log';
|
||||||
|
|
||||||
|
-- 我的设备
|
||||||
|
UPDATE sys_route SET name = 'my-device' WHERE route_id = 'my_device';
|
||||||
|
UPDATE sys_route SET name = 'my-device_status' WHERE route_id = 'my_device_status';
|
||||||
|
UPDATE sys_route SET name = 'my-device_power-control' WHERE route_id = 'my_device_power';
|
||||||
|
UPDATE sys_route SET name = 'my-device_remote-control' WHERE route_id = 'my_device_remote';
|
||||||
|
|
||||||
|
-- 设备申请
|
||||||
|
UPDATE sys_route SET name = 'my-application' WHERE route_id = 'my_application';
|
||||||
|
UPDATE sys_route SET name = 'my-application_apply' WHERE route_id = 'my_application_apply';
|
||||||
|
UPDATE sys_route SET name = 'my-application_my-list' WHERE route_id = 'my_application_list';
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 第二步:修复所有组件路径
|
||||||
|
-- 父路由用 layout.base,子路由用 view.xxx
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- 父路由
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id IN ('device', 'screen', 'user_manage', 'application', 'system', 'my_device', 'my_application');
|
||||||
|
|
||||||
|
-- 设备管理子路由
|
||||||
|
UPDATE sys_route SET component = 'view.device_list' WHERE route_id = 'device_list';
|
||||||
|
UPDATE sys_route SET component = 'view.device_online' WHERE route_id = 'device_online';
|
||||||
|
UPDATE sys_route SET component = 'view.device_power' WHERE route_id = 'device_power';
|
||||||
|
UPDATE sys_route SET component = 'view.device_monitor' WHERE route_id = 'device_monitor';
|
||||||
|
UPDATE sys_route SET component = 'view.device_group' WHERE route_id = 'device_group';
|
||||||
|
|
||||||
|
-- 屏幕监控子路由
|
||||||
|
UPDATE sys_route SET component = 'view.screen_wall' WHERE route_id = 'screen_wall';
|
||||||
|
UPDATE sys_route SET component = 'view.screen_control' WHERE route_id = 'screen_control';
|
||||||
|
UPDATE sys_route SET component = 'view.screen_record' WHERE route_id = 'screen_record';
|
||||||
|
|
||||||
|
-- 用户管理子路由
|
||||||
|
UPDATE sys_route SET component = 'view.user-manage_list' WHERE route_id = 'user_list';
|
||||||
|
UPDATE sys_route SET component = 'view.user-manage_role' WHERE route_id = 'user_role';
|
||||||
|
UPDATE sys_route SET component = 'view.user-manage_permission' WHERE route_id = 'user_permission';
|
||||||
|
|
||||||
|
-- 申请管理子路由
|
||||||
|
UPDATE sys_route SET component = 'view.application_approval' WHERE route_id = 'application_approval';
|
||||||
|
UPDATE sys_route SET component = 'view.application_history' WHERE route_id = 'application_history';
|
||||||
|
|
||||||
|
-- 系统设置子路由
|
||||||
|
UPDATE sys_route SET component = 'view.system_amt' WHERE route_id = 'system_amt';
|
||||||
|
UPDATE sys_route SET component = 'view.system_agent' WHERE route_id = 'system_agent';
|
||||||
|
UPDATE sys_route SET component = 'view.system_log' WHERE route_id = 'system_log';
|
||||||
|
|
||||||
|
-- 我的设备子路由
|
||||||
|
UPDATE sys_route SET component = 'view.my-device_status' WHERE route_id = 'my_device_status';
|
||||||
|
UPDATE sys_route SET component = 'view.my-device_power-control' WHERE route_id = 'my_device_power';
|
||||||
|
UPDATE sys_route SET component = 'view.my-device_remote-control' WHERE route_id = 'my_device_remote';
|
||||||
|
|
||||||
|
-- 设备申请子路由
|
||||||
|
UPDATE sys_route SET component = 'view.my-application_apply' WHERE route_id = 'my_application_apply';
|
||||||
|
UPDATE sys_route SET component = 'view.my-application_my-list' WHERE route_id = 'my_application_list';
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 第三步:更新角色菜单配置(最关键!)
|
||||||
|
-- 必须包含所有父路由和子路由的 name
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
UPDATE sys_role
|
||||||
|
SET menus = 'device,device_list,device_group,device_monitor,device_online,device_power,screen,screen_wall,screen_control,screen_record,user-manage,user-manage_list,user-manage_role,user-manage_permission,application,application_approval,application_history,system,system_agent,system_amt,system_log,my-device,my-device_status,my-device_remote-control,my-device_power-control,my-application,my-application_apply,my-application_my-list'
|
||||||
|
WHERE role_code = 'R_SUPER';
|
||||||
|
|
||||||
|
UPDATE sys_role
|
||||||
|
SET menus = 'device,device_list,device_group,device_monitor,device_online,device_power,screen,screen_wall,screen_control,screen_record,user-manage,user-manage_list,user-manage_role,application,application_approval,application_history'
|
||||||
|
WHERE role_code = 'R_ADMIN';
|
||||||
|
|
||||||
|
UPDATE sys_role
|
||||||
|
SET menus = 'my-device,my-device_status,my-device_remote-control,my-device_power-control,my-application,my-application_apply,my-application_my-list'
|
||||||
|
WHERE role_code = 'R_USER';
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 第四步:验证修复结果
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT '用户管理路由配置' AS '';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT route_id, name, path, component
|
||||||
|
FROM sys_route
|
||||||
|
WHERE route_id IN ('user_manage', 'user_list', 'user_role', 'user_permission')
|
||||||
|
ORDER BY order_num;
|
||||||
|
|
||||||
|
SELECT '' AS '';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT 'R_SUPER 角色菜单配置(前200字符)' AS '';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT role_code, role_name, SUBSTRING(menus, 1, 200) AS menus_preview
|
||||||
|
FROM sys_role
|
||||||
|
WHERE role_code = 'R_SUPER';
|
||||||
|
|
||||||
|
SELECT '' AS '';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT '检查子路由是否在角色配置中' AS '';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT
|
||||||
|
r.name AS route_name,
|
||||||
|
CASE
|
||||||
|
WHEN role.menus LIKE CONCAT('%', r.name, '%') THEN '✓ YES'
|
||||||
|
ELSE '✗ NO - 这会导致路由被过滤!'
|
||||||
|
END AS in_role_config
|
||||||
|
FROM sys_route r
|
||||||
|
CROSS JOIN sys_role role
|
||||||
|
WHERE role.role_code = 'R_SUPER'
|
||||||
|
AND r.route_id IN ('user_manage', 'user_list', 'user_role', 'user_permission')
|
||||||
|
ORDER BY r.order_num;
|
||||||
109
FIX_INSTRUCTIONS.md
Normal file
109
FIX_INSTRUCTIONS.md
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
# 菜单显示问题修复说明
|
||||||
|
|
||||||
|
## 问题原因
|
||||||
|
|
||||||
|
在实现动态路由权限时,我们将路由名称从连字符改为下划线格式:
|
||||||
|
- `user-manage` → `user_manage`
|
||||||
|
- `my-device` → `my_device`
|
||||||
|
- `my-application` → `my_application`
|
||||||
|
|
||||||
|
但是,**组件路径(component)必须与实际文件夹结构保持一致**,而实际文件夹使用的是连字符:
|
||||||
|
- `src/views/user-manage/`
|
||||||
|
- `src/views/my-device/`
|
||||||
|
- `src/views/my-application/`
|
||||||
|
|
||||||
|
这导致前端无法找到对应的组件文件,出现错误和菜单显示异常。
|
||||||
|
|
||||||
|
## 解决方案
|
||||||
|
|
||||||
|
保持以下规则:
|
||||||
|
1. **路由名称(name)** 使用下划线:`user_manage`, `my_device`, `my_application`
|
||||||
|
2. **组件路径(component)** 使用连字符匹配实际文件夹:`view.user-manage`, `view.my-device`
|
||||||
|
|
||||||
|
## 修复步骤
|
||||||
|
|
||||||
|
### 方法一:使用批处理脚本(推荐)
|
||||||
|
|
||||||
|
1. 双击运行 `fix_database.bat`
|
||||||
|
2. 按任意键开始执行
|
||||||
|
3. 等待修复完成
|
||||||
|
4. 重启后端服务
|
||||||
|
5. 刷新浏览器测试
|
||||||
|
|
||||||
|
### 方法二:手动执行 SQL
|
||||||
|
|
||||||
|
1. 打开 MySQL 客户端或命令行
|
||||||
|
2. 连接到数据库:
|
||||||
|
```bash
|
||||||
|
mysql -h localhost -P 3306 -u root -proot soybean_admin
|
||||||
|
```
|
||||||
|
3. 执行 SQL 文件:
|
||||||
|
```sql
|
||||||
|
source EXECUTE_THIS_FIX.sql;
|
||||||
|
```
|
||||||
|
或者直接复制 `EXECUTE_THIS_FIX.sql` 中的 SQL 语句执行
|
||||||
|
|
||||||
|
4. 重启后端服务
|
||||||
|
5. 刷新浏览器测试
|
||||||
|
|
||||||
|
## 验证修复
|
||||||
|
|
||||||
|
执行 SQL 后,应该看到类似以下的结果:
|
||||||
|
|
||||||
|
| 路由名称(下划线) | 路径 | 组件路径(连字符) |
|
||||||
|
|---|---|---|
|
||||||
|
| user_manage | /user-manage | layout.base$view.user-manage |
|
||||||
|
| user_manage_list | /user-manage/list | layout.base$view.user-manage_list |
|
||||||
|
| my_device | /my-device | layout.base$view.my-device |
|
||||||
|
| my_device_status | /my-device/status | layout.base$view.my-device_status |
|
||||||
|
|
||||||
|
## 重启服务
|
||||||
|
|
||||||
|
修复数据库后,必须重启后端服务:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
start.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
## 测试
|
||||||
|
|
||||||
|
1. 清除浏览器缓存(Ctrl+Shift+Delete)
|
||||||
|
2. 强制刷新页面(Ctrl+Shift+R)
|
||||||
|
3. 重新登录
|
||||||
|
4. 检查菜单是否正常显示
|
||||||
|
5. 检查是否还有重复菜单
|
||||||
|
6. 检查父子菜单层级是否正确
|
||||||
|
|
||||||
|
## 如果还有问题
|
||||||
|
|
||||||
|
如果修复后仍有问题,请检查:
|
||||||
|
|
||||||
|
1. 后端日志中是否有错误信息
|
||||||
|
2. 浏览器控制台是否有错误
|
||||||
|
3. 数据库中的 component 字段是否已正确更新
|
||||||
|
4. 是否已重启后端服务
|
||||||
|
5. 是否已清除浏览器缓存
|
||||||
|
|
||||||
|
## 技术细节
|
||||||
|
|
||||||
|
### 路由名称规则(用于权限判断)
|
||||||
|
- 使用下划线分隔
|
||||||
|
- 父菜单:0-1个下划线(如 `user_manage`, `device`)
|
||||||
|
- 子菜单:2个或以上下划线(如 `user_manage_list`, `device_online`)
|
||||||
|
|
||||||
|
### 组件路径规则(用于加载 Vue 组件)
|
||||||
|
- 必须与实际文件夹结构完全一致
|
||||||
|
- 文件夹使用连字符:`user-manage`, `my-device`
|
||||||
|
- 子文件夹也使用连字符:`power-control`, `my-list`
|
||||||
|
- 格式:`layout.base$view.{folder}_{subfolder}`
|
||||||
|
|
||||||
|
### 示例对照表
|
||||||
|
|
||||||
|
| 路由名称 | 文件夹路径 | 组件路径 |
|
||||||
|
|---|---|---|
|
||||||
|
| user_manage | src/views/user-manage/ | layout.base$view.user-manage |
|
||||||
|
| user_manage_list | src/views/user-manage/list/ | layout.base$view.user-manage_list |
|
||||||
|
| my_device | src/views/my-device/ | layout.base$view.my-device |
|
||||||
|
| my_device_status | src/views/my-device/status/ | layout.base$view.my-device_status |
|
||||||
|
| my_device_power | src/views/my-device/power-control/ | layout.base$view.my-device_power-control |
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Soybean
|
||||||
|
|
||||||
|
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.
|
||||||
187
MENU_SETUP.md
Normal file
187
MENU_SETUP.md
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
# 机房管控系统菜单配置指南
|
||||||
|
|
||||||
|
## 📋 菜单结构
|
||||||
|
|
||||||
|
### 管理员菜单 (R_SUPER, R_ADMIN)
|
||||||
|
|
||||||
|
1. **首页** 🏠
|
||||||
|
- 系统概览和统计信息
|
||||||
|
|
||||||
|
2. **设备管理** 💻
|
||||||
|
- 设备列表 - 所有设备的增删改查
|
||||||
|
- 在线状态 - 实时监控设备在线情况
|
||||||
|
- 电源管理 - 远程控制设备电源
|
||||||
|
- 远程监控 - 查看设备屏幕
|
||||||
|
- 设备分组 - 按维度分组管理(未来扩展)
|
||||||
|
|
||||||
|
3. **屏幕监控** 🖥
|
||||||
|
- 监控墙 - 多屏幕同时监控
|
||||||
|
- 单屏控制 - 单个设备控制
|
||||||
|
- 控制记录 - 操作审计
|
||||||
|
|
||||||
|
4. **用户管理** 👤
|
||||||
|
- 用户列表 - 用户增删改查
|
||||||
|
- 角色管理 - 角色配置
|
||||||
|
- 权限管理 - 权限分配(仅超级管理员)
|
||||||
|
|
||||||
|
5. **使用申请** 📄
|
||||||
|
- 申请审批 - 审批用户申请
|
||||||
|
- 使用记录 - 查看使用历史
|
||||||
|
|
||||||
|
6. **系统设置** ⚙ (仅超级管理员)
|
||||||
|
- AMT设置 - Intel AMT配置
|
||||||
|
- Agent设置 - 客户端程序管理
|
||||||
|
- 日志中心 - 系统日志查询
|
||||||
|
|
||||||
|
### 普通用户菜单 (R_USER)
|
||||||
|
|
||||||
|
1. **首页** 🏠
|
||||||
|
- 个人使用概览
|
||||||
|
|
||||||
|
2. **我的设备** 💻
|
||||||
|
- 设备状态 - 查看我的设备
|
||||||
|
- 电源控制 - 控制设备电源
|
||||||
|
- 远程控制 - 远程操作设备
|
||||||
|
|
||||||
|
3. **设备申请** 📄
|
||||||
|
- 申请使用 - 提交使用申请
|
||||||
|
- 我的申请 - 查看申请状态
|
||||||
|
|
||||||
|
## 🚀 部署步骤
|
||||||
|
|
||||||
|
### 1. 执行数据库脚本
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 登录 MySQL
|
||||||
|
mysql -u root -p
|
||||||
|
|
||||||
|
# 执行路由初始化脚本
|
||||||
|
source backend/src/main/resources/sql/add_all_routes.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
或者在 MySQL 客户端中直接执行 `backend/src/main/resources/sql/add_all_routes.sql` 文件。
|
||||||
|
|
||||||
|
### 2. 生成前端路由
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 在项目根目录执行
|
||||||
|
pnpm gen-route
|
||||||
|
```
|
||||||
|
|
||||||
|
这会自动扫描 `src/views` 目录并生成路由配置。
|
||||||
|
|
||||||
|
### 3. 重启服务
|
||||||
|
|
||||||
|
**后端:**
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
mvn spring-boot:run
|
||||||
|
```
|
||||||
|
|
||||||
|
**前端:**
|
||||||
|
```bash
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 测试菜单
|
||||||
|
|
||||||
|
**管理员账号:**
|
||||||
|
- 用户名:`admin`
|
||||||
|
- 密码:`admin123`
|
||||||
|
- 可见菜单:所有管理员菜单
|
||||||
|
|
||||||
|
**普通用户账号:**
|
||||||
|
- 用户名:`user`
|
||||||
|
- 密码:`user123`
|
||||||
|
- 可见菜单:仅普通用户菜单
|
||||||
|
|
||||||
|
## 📁 文件结构
|
||||||
|
|
||||||
|
```
|
||||||
|
src/views/
|
||||||
|
├── home/ # 首页
|
||||||
|
├── device/ # 设备管理
|
||||||
|
│ ├── index.vue
|
||||||
|
│ ├── _meta.ts
|
||||||
|
│ ├── list/ # 设备列表
|
||||||
|
│ ├── online/ # 在线状态
|
||||||
|
│ ├── power/ # 电源管理
|
||||||
|
│ ├── monitor/ # 远程监控
|
||||||
|
│ └── group/ # 设备分组
|
||||||
|
├── screen/ # 屏幕监控
|
||||||
|
│ ├── index.vue
|
||||||
|
│ ├── _meta.ts
|
||||||
|
│ ├── wall/ # 监控墙
|
||||||
|
│ ├── control/ # 单屏控制
|
||||||
|
│ └── record/ # 控制记录
|
||||||
|
├── user-manage/ # 用户管理
|
||||||
|
│ ├── index.vue
|
||||||
|
│ ├── _meta.ts
|
||||||
|
│ ├── list/ # 用户列表
|
||||||
|
│ ├── role/ # 角色管理
|
||||||
|
│ └── permission/ # 权限管理
|
||||||
|
├── application/ # 申请管理
|
||||||
|
│ ├── index.vue
|
||||||
|
│ ├── _meta.ts
|
||||||
|
│ ├── approval/ # 申请审批
|
||||||
|
│ └── history/ # 使用记录
|
||||||
|
├── system/ # 系统设置
|
||||||
|
│ ├── index.vue
|
||||||
|
│ ├── _meta.ts
|
||||||
|
│ ├── amt/ # AMT设置
|
||||||
|
│ ├── agent/ # Agent设置
|
||||||
|
│ └── log/ # 日志中心
|
||||||
|
├── my-device/ # 我的设备(普通用户)
|
||||||
|
│ ├── index.vue
|
||||||
|
│ ├── _meta.ts
|
||||||
|
│ ├── status/ # 设备状态
|
||||||
|
│ ├── power-control/ # 电源控制
|
||||||
|
│ └── remote-control/ # 远程控制
|
||||||
|
└── my-application/ # 设备申请(普通用户)
|
||||||
|
├── index.vue
|
||||||
|
├── _meta.ts
|
||||||
|
├── apply/ # 申请使用
|
||||||
|
└── my-list/ # 我的申请
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎨 路由元信息配置
|
||||||
|
|
||||||
|
每个页面的 `_meta.ts` 文件配置示例:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export default {
|
||||||
|
title: '设备管理', // 菜单标题
|
||||||
|
i18nKey: 'route.device', // 国际化key
|
||||||
|
icon: 'mdi:desktop-classic', // 图标
|
||||||
|
order: 2, // 排序
|
||||||
|
roles: ['R_SUPER', 'R_ADMIN'] // 可访问角色(可选)
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔐 权限说明
|
||||||
|
|
||||||
|
- **R_SUPER**: 超级管理员 - 所有权限
|
||||||
|
- **R_ADMIN**: 管理员 - 除系统设置外的所有权限
|
||||||
|
- **R_USER**: 普通用户 - 仅个人相关功能
|
||||||
|
|
||||||
|
## 📝 注意事项
|
||||||
|
|
||||||
|
1. 当前使用的是**静态路由模式** (`VITE_AUTH_ROUTE_MODE=static`)
|
||||||
|
2. 路由根据角色自动过滤,不同角色看到不同菜单
|
||||||
|
3. 所有页面都是示例页面,需要根据实际需求开发具体功能
|
||||||
|
4. 图标使用 Material Design Icons (mdi)
|
||||||
|
|
||||||
|
## 🔄 如何添加新菜单
|
||||||
|
|
||||||
|
1. 在 `src/views` 下创建新的页面文件夹
|
||||||
|
2. 创建 `index.vue` 页面组件
|
||||||
|
3. 创建 `_meta.ts` 配置文件
|
||||||
|
4. 运行 `pnpm gen-route` 生成路由
|
||||||
|
5. 在 `src/locales/langs/zh-cn.ts` 添加国际化配置
|
||||||
|
|
||||||
|
## 📞 技术支持
|
||||||
|
|
||||||
|
如有问题,请查看:
|
||||||
|
- 前端路由配置:`src/router/elegant/routes.ts`
|
||||||
|
- 后端路由数据:数据库 `sys_route` 表
|
||||||
|
- 国际化配置:`src/locales/langs/zh-cn.ts`
|
||||||
32
QUICK_FIX.md
Normal file
32
QUICK_FIX.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# 快速修复指南
|
||||||
|
|
||||||
|
## 问题
|
||||||
|
菜单显示异常、重复、前端报错
|
||||||
|
|
||||||
|
## 原因
|
||||||
|
路由名称改成了下划线,但组件路径也跟着改了,导致找不到实际的文件夹(文件夹用的是连字符)
|
||||||
|
|
||||||
|
## 修复(3步)
|
||||||
|
|
||||||
|
### 1. 执行数据库修复
|
||||||
|
双击运行:
|
||||||
|
```
|
||||||
|
fix_database.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 重启后端
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
start.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 刷新浏览器
|
||||||
|
按 `Ctrl + Shift + R` 强制刷新
|
||||||
|
|
||||||
|
## 完成!
|
||||||
|
|
||||||
|
现在菜单应该正常显示了,不会重复,也有正确的父子层级。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
详细说明请查看 `FIX_INSTRUCTIONS.md`
|
||||||
216
README.en_US.md
Normal file
216
README.en_US.md
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
<div align="center">
|
||||||
|
<img src="./public/favicon.svg" width="160" />
|
||||||
|
<h1>SoybeanAdmin</h1>
|
||||||
|
<span><a href="./README.md">中文</a> | English</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[](./LICENSE)
|
||||||
|
[](https://github.com/soybeanjs/soybean-admin)
|
||||||
|
[](https://github.com/soybeanjs/soybean-admin)
|
||||||
|
[](https://gitee.com/honghuangdc/soybean-admin)
|
||||||
|
[](https://gitcode.com/soybeanjs/soybean-admin)
|
||||||
|
|
||||||
|
<div style="display: flex; gap: 12px; align-items: center;">
|
||||||
|
<a href="https://trendshift.io/repositories/7963" target="_blank"><img src="https://trendshift.io/api/badge/repositories/7963" alt="soybeanjs%2Fsoybean-admin | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
||||||
|
<a href="https://hellogithub.com/repository/1298f27d5fe54959a16cf9686516ddb3" target="_blank"><img src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=1298f27d5fe54959a16cf9686516ddb3&claim_uid=IiDXWmP4TEntjbV" alt="Featured|HelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> If you think `SoybeanAdmin` is helpful to you, or you like our project, please give us a ⭐️ on GitHub. Your support is the driving force for us to continue to improve and add new features! Thank you for your support!
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> The `SoybeanAdmin` quick start series videos have been uploaded to [Bilibili](https://www.bilibili.com/video/BV1YKdRYXELC) Go online [click here](https://www.bilibili.com/video/BV1YKdRYXELC) Go check it out
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> `SoybeanAdmin` is planning to develop a `V2` version, see [plan list](https://github.com/soybeanjs/soybean-admin/issues/767)
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
[`SoybeanAdmin`](https://github.com/soybeanjs/soybean-admin) is a clean, elegant, beautiful and powerful admin template, based on the latest front-end technology stack, including Vue3, Vite7, TypeScript, Pinia and UnoCSS. It has built-in rich theme configuration and components, strict code specifications, and an automated file routing system. In addition, it also uses the online mock data solution based on ApiFox. `SoybeanAdmin` provides you with a one-stop admin solution, no additional configuration, and out of the box. It is also a best practice for learning cutting-edge technologies quickly.
|
||||||
|
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Cutting-edge technology application**: using the latest popular technology stack such as Vue3, Vite7, TypeScript, Pinia and UnoCSS.
|
||||||
|
- **Clear project architecture**: using pnpm monorepo architecture, clear structure, elegant and easy to understand.
|
||||||
|
- **Strict code specifications**: follow the [SoybeanJS specification](https://docs.soybeanjs.cn/standard), integrate eslint, prettier and simple-git-hooks to ensure the code is standardized.
|
||||||
|
- **TypeScript**: support strict type checking to improve code maintainability.
|
||||||
|
- **Rich theme configuration**: built-in a variety of theme configurations, perfectly integrated with UnoCSS.
|
||||||
|
- **Built-in internationalization solution**: easily realize multi-language support.
|
||||||
|
- **Automated file routing system**: automatically generate route import, declaration and type. For more details, please refer to [Elegant Router](https://github.com/soybeanjs/elegant-router).
|
||||||
|
- **Flexible permission routing**: support both front-end static routing and back-end dynamic routing.
|
||||||
|
- **Rich page components**: built-in a variety of pages and components, including 403, 404, 500 pages, as well as layout components, tag components, theme configuration components, etc.
|
||||||
|
- **Command line tool**: built-in efficient command line tool, git commit, delete file, release, etc.
|
||||||
|
- **Mobile adaptation**: perfectly support mobile terminal to realize adaptive layout.
|
||||||
|
|
||||||
|
|
||||||
|
## Version
|
||||||
|
|
||||||
|
- **NaiveUI Version:**
|
||||||
|
- [Preview Link](https://naive.soybeanjs.cn/)
|
||||||
|
- [Github Repository](https://github.com/soybeanjs/soybean-admin)
|
||||||
|
- [Gitee Repository](https://gitee.com/honghuangdc/soybean-admin)
|
||||||
|
- [Gitcode Repository](https://gitcode.com/soybeanjs/soybean-admin)
|
||||||
|
|
||||||
|
- **AntDesignVue Version:**
|
||||||
|
- [Preview Link](https://antd.soybeanjs.cn/)
|
||||||
|
- [Github Repository](https://github.com/soybeanjs/soybean-admin-antd)
|
||||||
|
- [Gitee Repository](https://gitee.com/honghuangdc/soybean-admin-antd)
|
||||||
|
- [Gitcode Repository](https://gitcode.com/soybeanjs/soybean-admin-antd)
|
||||||
|
|
||||||
|
- **ElementPlus Version:**
|
||||||
|
- [Preview Link](https://elp.soybeanjs.cn/)
|
||||||
|
- [Github Repository](https://github.com/soybeanjs/soybean-admin-element-plus)
|
||||||
|
- [Gitee Repository](https://gitee.com/honghuangdc/soybean-admin-element-plus)
|
||||||
|
- [Gitcode Repository](https://gitcode.com/soybeanjs/soybean-admin-element-plus)
|
||||||
|
|
||||||
|
- **Legacy Version:**
|
||||||
|
- [Preview Link](https://legacy.soybeanjs.cn/)
|
||||||
|
- [Github Repository](https://github.com/soybeanjs/soybean-admin/tree/legacy)
|
||||||
|
- [Gitee Repository](https://gitee.com/honghuangdc/soybean-admin/tree/legacy)
|
||||||
|
- [Gitcode Repository](https://gitcode.com/soybeanjs/soybean-admin/tree/legacy)
|
||||||
|
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [Link](https://docs.soybeanjs.cn)
|
||||||
|
- [Legacy Docs](https://legacy-docs.soybeanjs.cn)
|
||||||
|
|
||||||
|
## Example Images
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
**Environment Preparation**
|
||||||
|
|
||||||
|
Make sure your environment meets the following requirements:
|
||||||
|
|
||||||
|
- **git**: you need git to clone and manage project versions.
|
||||||
|
- **NodeJS**: >=20.19.0, recommended 20.19.0 or higher.
|
||||||
|
- **pnpm**: >= 10.5.0, recommended 10.5.0 or higher.
|
||||||
|
|
||||||
|
**Clone Project**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# github
|
||||||
|
git clone https://github.com/soybeanjs/soybean-admin.git
|
||||||
|
# gitee
|
||||||
|
git clone https://gitee.com/honghuangdc/soybean-admin.git
|
||||||
|
# gitcode
|
||||||
|
git clone https://gitcode.com/soybeanjs/soybean-admin.git
|
||||||
|
```
|
||||||
|
|
||||||
|
**Install Dependencies**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm i
|
||||||
|
```
|
||||||
|
> Since this project uses the pnpm monorepo management method, please do not use npm or yarn to install dependencies.
|
||||||
|
|
||||||
|
**Start Project**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
**Build Project**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm build
|
||||||
|
```
|
||||||
|
|
||||||
|
**Code Synchronization**
|
||||||
|
|
||||||
|
Refer to the [Code Synchronization](https://docs.soybeanjs.cn/guide/sync) document.
|
||||||
|
|
||||||
|
## Ecosystem
|
||||||
|
|
||||||
|
- [skyroc-admin](https://github.com/Ohh-889/skyroc-admin): SoybeanAdmin's React version implementation.
|
||||||
|
- [electron-mock-admin](https://github.com/lixin59/electron-mock-api): A Mock Api management system that helps front-end developers quickly implement interface mocks.
|
||||||
|
- [T-Shell](https://github.com/TheBlindM/T-Shell): A terminal emulator and SSH client with configurable command prompts.
|
||||||
|
- [pea](https://github.com/haitang1894/pea) : Adopting SpringBoot3.2 + JDK21, MyBatis-Plus, SpringSecurity security framework, etc., suitable for the simple permission system developed by [soybean-admin](https://gitee.com/honghuangdc/soybean-admin).
|
||||||
|
- [MalusAdmin](https://github.com/pridejoy/MalusAdmin): A backend management framework developed based on Vue3/TypeScript/NaiveUI and NET7 & Sqlsugar. It is implemented in the most original and simplest way, with a fresh and elegant front-end, a clear and elegant backend structure, and powerful functions.
|
||||||
|
- [PanisAdmin](https://github.com/paynezhuang/panis-admin): Adopting SpringBoot 3, SaToken, MySQL and other frameworks to develop and modify [soybean-admin](https://github.com/soybeanjs/soybean-admin) for the second time, adapting dynamic menu/button-level authorization. Retaining the original flavor, fresh and elegant, high-value back-end management system scaffold.
|
||||||
|
- [snail-job](https://github.com/aizuda/snail-job): A distributed task retry and task scheduling platform with "high performance, high value and high activity".
|
||||||
|
- [SuperApi](https://github.com/TmmTop/SuperApi): Quickly turn your idea into an online stable product! Entity-less library and table building, add, delete, change and check entity-less library table, support 15 kinds of condition query, as well as paging, list, unlimited tree list and other functions of the API deployment! With interface documentation, Auth authorisation, interface flow restriction, access to the client's real IP, advanced server caching components, dynamic APIs and other features, we look forward to your experience!
|
||||||
|
- [FastSoyAdmin](https://github.com/sleep1223/fast-soy-admin): A modern Management Platform based on FastAPI+Vue3+Naive UI.
|
||||||
|
- [ba](https://github.com/xiatianYa/Ba-Server): Backend service docking with soybean admin based on goFrame framework, adapted to dynamic routing, and interface authentication permissions.
|
||||||
|
- [soybean-admin-go](https://github.com/WgoW/soybean-admin-go):A Go backend service developed based on the Gin and GORM frameworks, integrated with the example branch of Soybean Admin. It supports dynamic routing and API permission authentication.
|
||||||
|
|
||||||
|
More ecosystem please refer to [Ecosystem](https://docs.soybeanjs.cn/awesome) document.
|
||||||
|
|
||||||
|
|
||||||
|
## How to Contribute
|
||||||
|
|
||||||
|
We warmly welcome and appreciate all forms of contributions. If you have any ideas or suggestions, please feel free to share them by submitting [pull requests](https://github.com/soybeanjs/soybean-admin/pulls) or creating GitHub [issue](https://github.com/soybeanjs/soybean-admin/issues/new).
|
||||||
|
|
||||||
|
## Git Commit Guidelines
|
||||||
|
|
||||||
|
This project has built-in `commit` command, you can execute `pnpm commit` to generate commit information that conforms to [Conventional Commits](https://www.conventionalcommits.org/) specification. When submitting PR, please be sure to use `commit` command to create commit information to ensure the standardization of information.
|
||||||
|
|
||||||
|
## Browser Support
|
||||||
|
|
||||||
|
It is recommended to use the latest version of Chrome in development for a better experience.
|
||||||
|
|
||||||
|
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png" alt="IE" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
|
||||||
|
|
||||||
|
## OpenSource Author
|
||||||
|
|
||||||
|
[Soybean](https://github.com/honghuangdc)
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
Thanks the following people for their contributions. If you want to contribute to this project, please refer to [How to Contribute](#how-to-contribute).
|
||||||
|
|
||||||
|
<a href="https://github.com/soybeanjs/soybean-admin/graphs/contributors">
|
||||||
|
<img src="https://contrib.rocks/image?repo=soybeanjs/soybean-admin" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Here are the most active contributors from the past year. Thank you all for your support, which has enabled the project's continued development.
|
||||||
|
|
||||||
|
<a href="https://openomy.com/soybeanjs/soybean-admin" target="_blank" style="display: block; width: 100%;" align="center">
|
||||||
|
<img src="https://www.openomy.com/svg?repo=soybeanjs/soybean-admin&chart=list&latestMonth=12" target="_blank" alt="Contribution Leaderboard" style="display: block; width: 100%;" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
## Communication
|
||||||
|
|
||||||
|
`SoybeanAdmin` is a completely open source and free project, helping developers to develop medium and large-scale management systems more conveniently. It also provides WeChat and QQ communication groups. If you have any questions, please feel free to ask in the group.
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p>QQ Group</p>
|
||||||
|
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/qq-soybean-admin-5.jpg" style="width:200px" />
|
||||||
|
</div>
|
||||||
|
<!-- <div>
|
||||||
|
<p>WeChat Group</p>
|
||||||
|
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/picgo/soybean-admin-wechat-0620.jpg" style="width:200px" />
|
||||||
|
</div> -->
|
||||||
|
<div>
|
||||||
|
<p>Add the following WeChat to invite to the WeChat group</p>
|
||||||
|
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/wechat-soybeanjs.jpg" style="width:200px" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Star Trend
|
||||||
|
|
||||||
|
[](https://star-history.com/#soybeanjs/soybean-admin&Date)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is based on the [MIT © 2021 Soybean](./LICENSE) protocol, for learning purposes only, please retain the author's copyright information for commercial use, the author does not guarantee and is not responsible for the software.
|
||||||
148
ROLE_PERMISSION_TEST.md
Normal file
148
ROLE_PERMISSION_TEST.md
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
# 角色权限功能测试指南
|
||||||
|
|
||||||
|
## 功能说明
|
||||||
|
|
||||||
|
现在系统已经实现了完整的基于角色的菜单权限控制:
|
||||||
|
|
||||||
|
1. **角色管理**:可以创建、编辑、删除角色
|
||||||
|
2. **权限配置**:可以为每个角色配置可访问的菜单
|
||||||
|
3. **用户管理**:可以为用户分配一个或多个角色
|
||||||
|
4. **权限生效**:用户登录后只能看到其角色配置的菜单
|
||||||
|
|
||||||
|
## 测试步骤
|
||||||
|
|
||||||
|
### 1. 创建测试角色
|
||||||
|
|
||||||
|
进入 **用户管理 > 角色管理**,创建以下测试角色:
|
||||||
|
|
||||||
|
- **角色1:设备管理员**
|
||||||
|
- 角色编码:`R_DEVICE_ADMIN`
|
||||||
|
- 角色名称:设备管理员
|
||||||
|
- 描述:负责设备管理相关功能
|
||||||
|
|
||||||
|
- **角色2:屏幕管理员**
|
||||||
|
- 角色编码:`R_SCREEN_ADMIN`
|
||||||
|
- 角色名称:屏幕管理员
|
||||||
|
- 描述:负责屏幕监控相关功能
|
||||||
|
|
||||||
|
### 2. 配置角色权限
|
||||||
|
|
||||||
|
进入 **用户管理 > 权限管理**:
|
||||||
|
|
||||||
|
#### 为"设备管理员"配置权限:
|
||||||
|
点击"配置权限"按钮,选择以下菜单:
|
||||||
|
- ✅ home(首页)
|
||||||
|
- ✅ device(设备管理)
|
||||||
|
- ✅ device_list(设备列表)
|
||||||
|
- ✅ device_group(设备分组)
|
||||||
|
- ✅ device_monitor(设备监控)
|
||||||
|
- ✅ device_online(在线设备)
|
||||||
|
- ✅ device_power(电源管理)
|
||||||
|
|
||||||
|
#### 为"屏幕管理员"配置权限:
|
||||||
|
点击"配置权限"按钮,选择以下菜单:
|
||||||
|
- ✅ home(首页)
|
||||||
|
- ✅ screen(屏幕监控)
|
||||||
|
- ✅ screen_wall(监控墙)
|
||||||
|
- ✅ screen_control(远程控制)
|
||||||
|
- ✅ screen_record(录像回放)
|
||||||
|
|
||||||
|
### 3. 创建测试用户
|
||||||
|
|
||||||
|
进入 **用户管理 > 用户列表**:
|
||||||
|
|
||||||
|
#### 创建设备管理员用户:
|
||||||
|
- 用户ID:`device_admin`
|
||||||
|
- 用户名:设备管理员
|
||||||
|
- 密码:`123456`
|
||||||
|
- 角色:选择"设备管理员"
|
||||||
|
- 状态:启用
|
||||||
|
|
||||||
|
#### 创建屏幕管理员用户:
|
||||||
|
- 用户ID:`screen_admin`
|
||||||
|
- 用户名:屏幕管理员
|
||||||
|
- 密码:`123456`
|
||||||
|
- 角色:选择"屏幕管理员"
|
||||||
|
- 状态:启用
|
||||||
|
|
||||||
|
#### 创建多角色用户:
|
||||||
|
- 用户ID:`multi_admin`
|
||||||
|
- 用户名:多角色管理员
|
||||||
|
- 密码:`123456`
|
||||||
|
- 角色:同时选择"设备管理员"和"屏幕管理员"
|
||||||
|
- 状态:启用
|
||||||
|
|
||||||
|
### 4. 验证权限
|
||||||
|
|
||||||
|
#### 测试1:设备管理员登录
|
||||||
|
1. 退出当前账号
|
||||||
|
2. 使用 `device_admin` / `123456` 登录
|
||||||
|
3. **预期结果**:
|
||||||
|
- ✅ 可以看到"首页"菜单
|
||||||
|
- ✅ 可以看到"设备管理"及其所有子菜单
|
||||||
|
- ❌ 看不到"屏幕监控"菜单
|
||||||
|
- ❌ 看不到"用户管理"菜单
|
||||||
|
|
||||||
|
#### 测试2:屏幕管理员登录
|
||||||
|
1. 退出当前账号
|
||||||
|
2. 使用 `screen_admin` / `123456` 登录
|
||||||
|
3. **预期结果**:
|
||||||
|
- ✅ 可以看到"首页"菜单
|
||||||
|
- ✅ 可以看到"屏幕监控"及其所有子菜单
|
||||||
|
- ❌ 看不到"设备管理"菜单
|
||||||
|
- ❌ 看不到"用户管理"菜单
|
||||||
|
|
||||||
|
#### 测试3:多角色用户登录
|
||||||
|
1. 退出当前账号
|
||||||
|
2. 使用 `multi_admin` / `123456` 登录
|
||||||
|
3. **预期结果**:
|
||||||
|
- ✅ 可以看到"首页"菜单
|
||||||
|
- ✅ 可以看到"设备管理"及其所有子菜单
|
||||||
|
- ✅ 可以看到"屏幕监控"及其所有子菜单
|
||||||
|
- ❌ 看不到"用户管理"菜单
|
||||||
|
|
||||||
|
#### 测试4:超级管理员
|
||||||
|
1. 使用 `admin` / `admin123` 登录
|
||||||
|
2. **预期结果**:
|
||||||
|
- ✅ 可以看到所有菜单(需要先为 R_SUPER 角色配置所有菜单权限)
|
||||||
|
|
||||||
|
## 技术实现
|
||||||
|
|
||||||
|
### 后端实现
|
||||||
|
- `RouteService.getUserRoutes()` 方法会:
|
||||||
|
1. 查询用户的角色列表
|
||||||
|
2. 从 `sys_role` 表查询角色配置的菜单
|
||||||
|
3. 合并所有角色的菜单权限
|
||||||
|
4. 返回用户可访问的路由列表
|
||||||
|
|
||||||
|
### 前端实现
|
||||||
|
- 用户列表页面动态加载角色选项
|
||||||
|
- 角色选择器显示角色中文名称
|
||||||
|
- 表格中显示角色名称(带颜色标签)
|
||||||
|
|
||||||
|
### 数据库
|
||||||
|
- `sys_role.menus` 字段存储角色可访问的菜单(逗号分隔)
|
||||||
|
- `sys_user.roles` 字段存储用户的角色列表(逗号分隔)
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **首次使用**:需要先为现有的 `R_SUPER` 和 `R_ADMIN` 角色配置菜单权限
|
||||||
|
2. **角色状态**:只有启用状态的角色才会生效
|
||||||
|
3. **多角色**:用户可以拥有多个角色,权限会合并
|
||||||
|
4. **空权限**:如果角色没有配置任何菜单,用户将看不到任何菜单(除了首页)
|
||||||
|
5. **实时生效**:修改角色权限后,用户需要重新登录才能看到变化
|
||||||
|
|
||||||
|
## 故障排查
|
||||||
|
|
||||||
|
### 问题1:用户看不到任何菜单
|
||||||
|
- 检查用户是否分配了角色
|
||||||
|
- 检查角色是否为启用状态
|
||||||
|
- 检查角色是否配置了菜单权限
|
||||||
|
|
||||||
|
### 问题2:权限修改后没有生效
|
||||||
|
- 用户需要退出并重新登录
|
||||||
|
- 检查后端日志是否有错误
|
||||||
|
|
||||||
|
### 问题3:角色选择器是空的
|
||||||
|
- 检查是否有启用状态的角色
|
||||||
|
- 检查浏览器控制台是否有 API 错误
|
||||||
42
backend/.gitignore
vendored
Normal file
42
backend/.gitignore
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
HELP.md
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Maven ###
|
||||||
|
.mvn/
|
||||||
|
mvnw
|
||||||
|
mvnw.cmd
|
||||||
|
|
||||||
|
### Logs ###
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
208
backend/README.md
Normal file
208
backend/README.md
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
# Soybean Admin Backend
|
||||||
|
|
||||||
|
基于 Spring Boot 3.2 的后端服务,为 Soybean Admin 前端提供 API 支持。
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
- Spring Boot 3.2.0
|
||||||
|
- MyBatis Plus 3.5.5
|
||||||
|
- MySQL 8.0+
|
||||||
|
- JWT (jjwt 0.12.3)
|
||||||
|
- Lombok
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 环境要求
|
||||||
|
|
||||||
|
- JDK 17+
|
||||||
|
- Maven 3.6+
|
||||||
|
- MySQL 8.0+
|
||||||
|
|
||||||
|
### 2. 数据库初始化
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 登录 MySQL
|
||||||
|
mysql -u root -p
|
||||||
|
|
||||||
|
# 执行初始化脚本
|
||||||
|
source src/main/resources/sql/init.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
或者直接在 MySQL 客户端中执行 `src/main/resources/sql/init.sql` 文件。
|
||||||
|
|
||||||
|
### 3. 配置数据库
|
||||||
|
|
||||||
|
编辑 `src/main/resources/application.yml`,确认数据库配置:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
url: jdbc:mysql://localhost:3306/soybean_admin?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
|
||||||
|
username: root
|
||||||
|
password: root
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 启动项目
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 使用 Maven 启动
|
||||||
|
mvn spring-boot:run
|
||||||
|
|
||||||
|
# 或者先编译再运行
|
||||||
|
mvn clean package
|
||||||
|
java -jar target/soybean-admin-backend-1.0.0.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
服务将在 `http://localhost:8080` 启动。
|
||||||
|
|
||||||
|
## 默认账号
|
||||||
|
|
||||||
|
| 用户名 | 密码 | 角色 | 说明 |
|
||||||
|
|--------|------|------|------|
|
||||||
|
| admin | admin123 | R_SUPER, R_ADMIN | 超级管理员 |
|
||||||
|
| user | user123 | R_USER | 普通用户 |
|
||||||
|
|
||||||
|
## API 接口
|
||||||
|
|
||||||
|
### 认证接口
|
||||||
|
|
||||||
|
#### 1. 登录
|
||||||
|
```
|
||||||
|
POST /auth/login
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"userName": "admin",
|
||||||
|
"password": "admin123"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. 获取用户信息
|
||||||
|
```
|
||||||
|
GET /auth/getUserInfo
|
||||||
|
Authorization: Bearer {token}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. 刷新令牌
|
||||||
|
```
|
||||||
|
POST /auth/refreshToken
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"refreshToken": "xxx"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 路由接口
|
||||||
|
|
||||||
|
#### 1. 获取常量路由
|
||||||
|
```
|
||||||
|
GET /route/getConstantRoutes
|
||||||
|
Authorization: Bearer {token}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. 获取用户路由
|
||||||
|
```
|
||||||
|
GET /route/getUserRoutes
|
||||||
|
Authorization: Bearer {token}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. 检查路由是否存在
|
||||||
|
```
|
||||||
|
GET /route/isRouteExist?routeName=home
|
||||||
|
Authorization: Bearer {token}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 响应格式
|
||||||
|
|
||||||
|
所有接口统一返回格式:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "0000",
|
||||||
|
"msg": "success",
|
||||||
|
"data": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- `code`: "0000" 表示成功,其他表示失败
|
||||||
|
- `msg`: 响应消息
|
||||||
|
- `data`: 响应数据
|
||||||
|
|
||||||
|
## 错误码
|
||||||
|
|
||||||
|
| 错误码 | 说明 |
|
||||||
|
|--------|------|
|
||||||
|
| 0000 | 成功 |
|
||||||
|
| 1111 | 通用错误 |
|
||||||
|
| 7777 | 需要弹窗提示的登出 |
|
||||||
|
| 8888 | 直接登出 |
|
||||||
|
| 9999 | Token 过期 |
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
backend/
|
||||||
|
├── src/main/java/com/soybean/admin/
|
||||||
|
│ ├── common/ # 通用类
|
||||||
|
│ │ └── Result.java # 统一响应格式
|
||||||
|
│ ├── config/ # 配置类
|
||||||
|
│ │ ├── WebConfig.java
|
||||||
|
│ │ └── InterceptorConfig.java
|
||||||
|
│ ├── controller/ # 控制器
|
||||||
|
│ │ ├── AuthController.java
|
||||||
|
│ │ └── RouteController.java
|
||||||
|
│ ├── dto/ # 数据传输对象
|
||||||
|
│ ├── entity/ # 实体类
|
||||||
|
│ │ ├── User.java
|
||||||
|
│ │ └── Route.java
|
||||||
|
│ ├── interceptor/ # 拦截器
|
||||||
|
│ │ └── AuthInterceptor.java
|
||||||
|
│ ├── mapper/ # MyBatis Mapper
|
||||||
|
│ │ ├── UserMapper.java
|
||||||
|
│ │ └── RouteMapper.java
|
||||||
|
│ ├── service/ # 服务层
|
||||||
|
│ │ ├── AuthService.java
|
||||||
|
│ │ └── RouteService.java
|
||||||
|
│ └── util/ # 工具类
|
||||||
|
│ └── JwtUtil.java
|
||||||
|
└── src/main/resources/
|
||||||
|
├── application.yml # 配置文件
|
||||||
|
└── sql/
|
||||||
|
└── init.sql # 数据库初始化脚本
|
||||||
|
```
|
||||||
|
|
||||||
|
## 前端配置
|
||||||
|
|
||||||
|
修改前端项目的 `.env.test` 或 `.env.prod` 文件:
|
||||||
|
|
||||||
|
```env
|
||||||
|
VITE_SERVICE_BASE_URL=http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
## 开发说明
|
||||||
|
|
||||||
|
### 添加新接口
|
||||||
|
|
||||||
|
1. 在 `entity` 包中创建实体类
|
||||||
|
2. 在 `mapper` 包中创建 Mapper 接口
|
||||||
|
3. 在 `service` 包中创建服务类
|
||||||
|
4. 在 `controller` 包中创建控制器
|
||||||
|
5. 在 `dto` 包中创建 DTO 类(如需要)
|
||||||
|
|
||||||
|
### 权限控制
|
||||||
|
|
||||||
|
- 不需要认证的接口在 `InterceptorConfig` 中配置 `excludePathPatterns`
|
||||||
|
- 需要特定角色的路由在数据库 `sys_route` 表的 `roles` 字段配置
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. 生产环境请修改 JWT 密钥(`application.yml` 中的 `jwt.secret`)
|
||||||
|
2. 生产环境请使用加密的密码存储(建议使用 BCrypt)
|
||||||
|
3. 建议配置日志输出到文件
|
||||||
|
4. 建议添加全局异常处理
|
||||||
|
5. 建议添加接口限流和防重放攻击
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
96
backend/pom.xml
Normal file
96
backend/pom.xml
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||||
|
https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.7.18</version>
|
||||||
|
<relativePath/>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>com.soybean</groupId>
|
||||||
|
<artifactId>soybean-admin-backend</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<name>soybean-admin-backend</name>
|
||||||
|
<description>Backend for Soybean Admin</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>17</java.version>
|
||||||
|
<mybatis-plus.version>3.5.5</mybatis-plus.version>
|
||||||
|
<jwt.version>0.11.5</jwt.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- Spring Boot Web -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spring Boot Validation -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- MySQL Driver -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-j</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- MyBatis Plus -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<version>${mybatis-plus.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JWT -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-api</artifactId>
|
||||||
|
<version>${jwt.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-impl</artifactId>
|
||||||
|
<version>${jwt.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
|
<version>${jwt.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Lombok -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spring Boot Test -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package com.soybean.admin;
|
||||||
|
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@MapperScan("com.soybean.admin.mapper")
|
||||||
|
public class SoybeanAdminApplication {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SoybeanAdminApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
29
backend/src/main/java/com/soybean/admin/common/Result.java
Normal file
29
backend/src/main/java/com/soybean/admin/common/Result.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package com.soybean.admin.common;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Result<T> {
|
||||||
|
private String code;
|
||||||
|
private String msg;
|
||||||
|
private T data;
|
||||||
|
|
||||||
|
public static <T> Result<T> success(T data) {
|
||||||
|
Result<T> result = new Result<>();
|
||||||
|
result.setCode("0000");
|
||||||
|
result.setMsg("success");
|
||||||
|
result.setData(data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> error(String code, String msg) {
|
||||||
|
Result<T> result = new Result<>();
|
||||||
|
result.setCode(code);
|
||||||
|
result.setMsg(msg);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> error(String msg) {
|
||||||
|
return error("1111", msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.soybean.admin.config;
|
||||||
|
|
||||||
|
import com.soybean.admin.interceptor.AuthInterceptor;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class InterceptorConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthInterceptor authInterceptor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
registry.addInterceptor(authInterceptor)
|
||||||
|
.addPathPatterns("/**")
|
||||||
|
.excludePathPatterns(
|
||||||
|
"/auth/login",
|
||||||
|
"/auth/error"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.soybean.admin.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class WebConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addCorsMappings(CorsRegistry registry) {
|
||||||
|
registry.addMapping("/**")
|
||||||
|
.allowedOriginPatterns("*")
|
||||||
|
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||||
|
.allowedHeaders("*")
|
||||||
|
.allowCredentials(true)
|
||||||
|
.maxAge(3600);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
package com.soybean.admin.controller;
|
||||||
|
|
||||||
|
import com.soybean.admin.common.Result;
|
||||||
|
import com.soybean.admin.dto.LoginRequest;
|
||||||
|
import com.soybean.admin.dto.LoginToken;
|
||||||
|
import com.soybean.admin.dto.UserInfo;
|
||||||
|
import com.soybean.admin.service.AuthService;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/auth")
|
||||||
|
public class AuthController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthService authService;
|
||||||
|
|
||||||
|
@PostMapping("/login")
|
||||||
|
public Result<LoginToken> login(@Valid @RequestBody LoginRequest request) {
|
||||||
|
try {
|
||||||
|
LoginToken token = authService.login(request.getUserName(), request.getPassword());
|
||||||
|
return Result.success(token);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getUserInfo")
|
||||||
|
public Result<UserInfo> getUserInfo(@RequestAttribute("userId") String userId) {
|
||||||
|
try {
|
||||||
|
UserInfo userInfo = authService.getUserInfo(userId);
|
||||||
|
return Result.success(userInfo);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/refreshToken")
|
||||||
|
public Result<LoginToken> refreshToken(@RequestBody Map<String, String> request) {
|
||||||
|
try {
|
||||||
|
String refreshToken = request.get("refreshToken");
|
||||||
|
LoginToken token = authService.refreshToken(refreshToken);
|
||||||
|
return Result.success(token);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("9999", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/error")
|
||||||
|
public Result<Void> error(@RequestParam String code, @RequestParam String msg) {
|
||||||
|
return Result.error(code, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.soybean.admin.controller;
|
||||||
|
|
||||||
|
import com.soybean.admin.common.Result;
|
||||||
|
import com.soybean.admin.service.PermissionService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/permission")
|
||||||
|
public class PermissionController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PermissionService permissionService;
|
||||||
|
|
||||||
|
// 权限管理现在通过角色管理页面的menus字段实现
|
||||||
|
// 不需要单独的权限接口
|
||||||
|
}
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
package com.soybean.admin.controller;
|
||||||
|
|
||||||
|
import com.soybean.admin.common.Result;
|
||||||
|
import com.soybean.admin.dto.PageRequest;
|
||||||
|
import com.soybean.admin.dto.PageResponse;
|
||||||
|
import com.soybean.admin.dto.RoleDTO;
|
||||||
|
import com.soybean.admin.service.RoleService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/role")
|
||||||
|
public class RoleController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RoleService roleService;
|
||||||
|
|
||||||
|
@PostMapping("/list")
|
||||||
|
public Result<PageResponse<RoleDTO>> getRoleList(@RequestBody PageRequest request) {
|
||||||
|
try {
|
||||||
|
PageResponse<RoleDTO> response = roleService.getRoleList(request);
|
||||||
|
return Result.success(response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/all")
|
||||||
|
public Result<List<RoleDTO>> getAllRoles() {
|
||||||
|
try {
|
||||||
|
List<RoleDTO> roles = roleService.getAllRoles();
|
||||||
|
return Result.success(roles);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public Result<RoleDTO> getRoleById(@PathVariable Long id) {
|
||||||
|
try {
|
||||||
|
RoleDTO role = roleService.getRoleById(id);
|
||||||
|
return Result.success(role);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public Result<Void> createRole(@Valid @RequestBody RoleDTO dto) {
|
||||||
|
try {
|
||||||
|
roleService.createRole(dto);
|
||||||
|
return Result.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
public Result<Void> updateRole(@Valid @RequestBody RoleDTO dto) {
|
||||||
|
try {
|
||||||
|
roleService.updateRole(dto);
|
||||||
|
return Result.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public Result<Void> deleteRole(@PathVariable Long id) {
|
||||||
|
try {
|
||||||
|
roleService.deleteRole(id);
|
||||||
|
return Result.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/batchDelete")
|
||||||
|
public Result<Void> batchDelete(@RequestBody List<Long> ids) {
|
||||||
|
try {
|
||||||
|
roleService.batchDelete(ids);
|
||||||
|
return Result.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
package com.soybean.admin.controller;
|
||||||
|
|
||||||
|
import com.soybean.admin.common.Result;
|
||||||
|
import com.soybean.admin.dto.MenuRoute;
|
||||||
|
import com.soybean.admin.dto.UserRoute;
|
||||||
|
import com.soybean.admin.service.RouteService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/route")
|
||||||
|
public class RouteController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RouteService routeService;
|
||||||
|
|
||||||
|
@GetMapping("/getConstantRoutes")
|
||||||
|
public Result<List<MenuRoute>> getConstantRoutes() {
|
||||||
|
try {
|
||||||
|
List<MenuRoute> routes = routeService.getConstantRoutes();
|
||||||
|
return Result.success(routes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getUserRoutes")
|
||||||
|
public Result<UserRoute> getUserRoutes(@RequestAttribute("userId") String userId) {
|
||||||
|
try {
|
||||||
|
UserRoute userRoute = routeService.getUserRoutes(userId);
|
||||||
|
return Result.success(userRoute);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/isRouteExist")
|
||||||
|
public Result<Boolean> isRouteExist(@RequestParam String routeName) {
|
||||||
|
try {
|
||||||
|
boolean exists = routeService.isRouteExist(routeName);
|
||||||
|
return Result.success(exists);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getAllMenus")
|
||||||
|
public Result<List<MenuRoute>> getAllMenus() {
|
||||||
|
try {
|
||||||
|
List<MenuRoute> menus = routeService.getConstantRoutes();
|
||||||
|
return Result.success(menus);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
package com.soybean.admin.controller;
|
||||||
|
|
||||||
|
import com.soybean.admin.common.Result;
|
||||||
|
import com.soybean.admin.dto.PageRequest;
|
||||||
|
import com.soybean.admin.dto.PageResponse;
|
||||||
|
import com.soybean.admin.dto.UserDTO;
|
||||||
|
import com.soybean.admin.service.UserService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/user")
|
||||||
|
public class UserController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
@PostMapping("/list")
|
||||||
|
public Result<PageResponse<UserDTO>> getUserList(@RequestBody PageRequest request) {
|
||||||
|
try {
|
||||||
|
PageResponse<UserDTO> response = userService.getUserList(request);
|
||||||
|
return Result.success(response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public Result<UserDTO> getUserById(@PathVariable Long id) {
|
||||||
|
try {
|
||||||
|
UserDTO user = userService.getUserById(id);
|
||||||
|
return Result.success(user);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public Result<Void> createUser(@Valid @RequestBody UserDTO dto) {
|
||||||
|
try {
|
||||||
|
userService.createUser(dto);
|
||||||
|
return Result.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
public Result<Void> updateUser(@Valid @RequestBody UserDTO dto) {
|
||||||
|
try {
|
||||||
|
userService.updateUser(dto);
|
||||||
|
return Result.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public Result<Void> deleteUser(@PathVariable Long id) {
|
||||||
|
try {
|
||||||
|
userService.deleteUser(id);
|
||||||
|
return Result.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/batchDelete")
|
||||||
|
public Result<Void> batchDelete(@RequestBody List<Long> ids) {
|
||||||
|
try {
|
||||||
|
userService.batchDelete(ids);
|
||||||
|
return Result.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package com.soybean.admin.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class LoginRequest {
|
||||||
|
@NotBlank(message = "用户名不能为空")
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
@NotBlank(message = "密码不能为空")
|
||||||
|
private String password;
|
||||||
|
}
|
||||||
13
backend/src/main/java/com/soybean/admin/dto/LoginToken.java
Normal file
13
backend/src/main/java/com/soybean/admin/dto/LoginToken.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package com.soybean.admin.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class LoginToken {
|
||||||
|
private String token;
|
||||||
|
private String refreshToken;
|
||||||
|
}
|
||||||
16
backend/src/main/java/com/soybean/admin/dto/MenuRoute.java
Normal file
16
backend/src/main/java/com/soybean/admin/dto/MenuRoute.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package com.soybean.admin.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class MenuRoute {
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private String path;
|
||||||
|
private String component;
|
||||||
|
private Boolean props;
|
||||||
|
private Map<String, Object> meta;
|
||||||
|
private List<MenuRoute> children;
|
||||||
|
}
|
||||||
13
backend/src/main/java/com/soybean/admin/dto/PageRequest.java
Normal file
13
backend/src/main/java/com/soybean/admin/dto/PageRequest.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package com.soybean.admin.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PageRequest {
|
||||||
|
private Integer current = 1;
|
||||||
|
private Integer size = 10;
|
||||||
|
private String userName;
|
||||||
|
private String roleName;
|
||||||
|
private String permissionName;
|
||||||
|
private Integer status;
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.soybean.admin.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class PageResponse<T> {
|
||||||
|
private List<T> records;
|
||||||
|
private Long total;
|
||||||
|
private Integer current;
|
||||||
|
private Integer size;
|
||||||
|
}
|
||||||
23
backend/src/main/java/com/soybean/admin/dto/RoleDTO.java
Normal file
23
backend/src/main/java/com/soybean/admin/dto/RoleDTO.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package com.soybean.admin.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class RoleDTO {
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotBlank(message = "角色编码不能为空")
|
||||||
|
private String roleCode;
|
||||||
|
|
||||||
|
@NotBlank(message = "角色名称不能为空")
|
||||||
|
private String roleName;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
private String menus;
|
||||||
|
private Integer status;
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
}
|
||||||
23
backend/src/main/java/com/soybean/admin/dto/UserDTO.java
Normal file
23
backend/src/main/java/com/soybean/admin/dto/UserDTO.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package com.soybean.admin.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class UserDTO {
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotBlank(message = "用户ID不能为空")
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
@NotBlank(message = "用户名不能为空")
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private String roles;
|
||||||
|
|
||||||
|
private String buttons;
|
||||||
|
|
||||||
|
private Integer status;
|
||||||
|
}
|
||||||
16
backend/src/main/java/com/soybean/admin/dto/UserInfo.java
Normal file
16
backend/src/main/java/com/soybean/admin/dto/UserInfo.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package com.soybean.admin.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class UserInfo {
|
||||||
|
private String userId;
|
||||||
|
private String userName;
|
||||||
|
private List<String> roles;
|
||||||
|
private List<String> buttons;
|
||||||
|
}
|
||||||
14
backend/src/main/java/com/soybean/admin/dto/UserRoute.java
Normal file
14
backend/src/main/java/com/soybean/admin/dto/UserRoute.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package com.soybean.admin.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class UserRoute {
|
||||||
|
private List<MenuRoute> routes;
|
||||||
|
private String home;
|
||||||
|
}
|
||||||
24
backend/src/main/java/com/soybean/admin/entity/Role.java
Normal file
24
backend/src/main/java/com/soybean/admin/entity/Role.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package com.soybean.admin.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("sys_role")
|
||||||
|
public class Role {
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String roleCode;
|
||||||
|
private String roleName;
|
||||||
|
private String description;
|
||||||
|
private String menus;
|
||||||
|
private Integer status;
|
||||||
|
private Integer deleted;
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
}
|
||||||
25
backend/src/main/java/com/soybean/admin/entity/Route.java
Normal file
25
backend/src/main/java/com/soybean/admin/entity/Route.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package com.soybean.admin.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("sys_route")
|
||||||
|
public class Route {
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
private String routeId;
|
||||||
|
private String name;
|
||||||
|
private String path;
|
||||||
|
private String component;
|
||||||
|
private String meta;
|
||||||
|
private String roles;
|
||||||
|
private Integer orderNum;
|
||||||
|
private Integer status;
|
||||||
|
private Integer deleted;
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
}
|
||||||
23
backend/src/main/java/com/soybean/admin/entity/User.java
Normal file
23
backend/src/main/java/com/soybean/admin/entity/User.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package com.soybean.admin.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("sys_user")
|
||||||
|
public class User {
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
private String userId;
|
||||||
|
private String userName;
|
||||||
|
private String password;
|
||||||
|
private String roles;
|
||||||
|
private String buttons;
|
||||||
|
private Integer status;
|
||||||
|
private Integer deleted;
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.soybean.admin.exception;
|
||||||
|
|
||||||
|
import com.soybean.admin.common.Result;
|
||||||
|
import org.springframework.validation.BindException;
|
||||||
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public Result<Void> handleException(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return Result.error("1111", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(RuntimeException.class)
|
||||||
|
public Result<Void> handleRuntimeException(RuntimeException e) {
|
||||||
|
return Result.error("1111", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
|
public Result<Void> handleValidationException(MethodArgumentNotValidException e) {
|
||||||
|
String message = e.getBindingResult().getFieldError() != null ?
|
||||||
|
e.getBindingResult().getFieldError().getDefaultMessage() : "参数校验失败";
|
||||||
|
return Result.error("1111", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(BindException.class)
|
||||||
|
public Result<Void> handleBindException(BindException e) {
|
||||||
|
String message = e.getBindingResult().getFieldError() != null ?
|
||||||
|
e.getBindingResult().getFieldError().getDefaultMessage() : "参数绑定失败";
|
||||||
|
return Result.error("1111", message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package com.soybean.admin.interceptor;
|
||||||
|
|
||||||
|
import com.soybean.admin.util.JwtUtil;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AuthInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtUtil jwtUtil;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||||
|
if ("OPTIONS".equals(request.getMethod())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String authorization = request.getHeader("Authorization");
|
||||||
|
if (authorization != null && authorization.startsWith("Bearer ")) {
|
||||||
|
String token = authorization.substring(7);
|
||||||
|
if (jwtUtil.validateToken(token)) {
|
||||||
|
String userId = jwtUtil.getUserIdFromToken(token);
|
||||||
|
request.setAttribute("userId", userId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.soybean.admin.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.soybean.admin.entity.Role;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface RoleMapper extends BaseMapper<Role> {
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.soybean.admin.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.soybean.admin.entity.Route;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface RouteMapper extends BaseMapper<Route> {
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.soybean.admin.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.soybean.admin.entity.User;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface UserMapper extends BaseMapper<User> {
|
||||||
|
}
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
package com.soybean.admin.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.soybean.admin.dto.LoginToken;
|
||||||
|
import com.soybean.admin.dto.UserInfo;
|
||||||
|
import com.soybean.admin.entity.User;
|
||||||
|
import com.soybean.admin.mapper.UserMapper;
|
||||||
|
import com.soybean.admin.util.JwtUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class AuthService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserMapper userMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtUtil jwtUtil;
|
||||||
|
|
||||||
|
public LoginToken login(String userName, String password) {
|
||||||
|
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(User::getUserName, userName);
|
||||||
|
User user = userMapper.selectOne(wrapper);
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
throw new RuntimeException("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user.getPassword().equals(password)) {
|
||||||
|
throw new RuntimeException("密码错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.getStatus() != 1) {
|
||||||
|
throw new RuntimeException("用户已被禁用");
|
||||||
|
}
|
||||||
|
|
||||||
|
String token = jwtUtil.generateToken(user.getUserId(), user.getUserName());
|
||||||
|
String refreshToken = jwtUtil.generateRefreshToken(user.getUserId());
|
||||||
|
|
||||||
|
return new LoginToken(token, refreshToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserInfo getUserInfo(String userId) {
|
||||||
|
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(User::getUserId, userId);
|
||||||
|
User user = userMapper.selectOne(wrapper);
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
throw new RuntimeException("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> roles = user.getRoles() != null ?
|
||||||
|
Arrays.asList(user.getRoles().split(",")) : Collections.emptyList();
|
||||||
|
List<String> buttons = user.getButtons() != null ?
|
||||||
|
Arrays.asList(user.getButtons().split(",")) : Collections.emptyList();
|
||||||
|
|
||||||
|
return new UserInfo(user.getUserId(), user.getUserName(), roles, buttons);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginToken refreshToken(String refreshToken) {
|
||||||
|
if (!jwtUtil.validateToken(refreshToken)) {
|
||||||
|
throw new RuntimeException("刷新令牌无效或已过期");
|
||||||
|
}
|
||||||
|
|
||||||
|
String userId = jwtUtil.getUserIdFromToken(refreshToken);
|
||||||
|
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(User::getUserId, userId);
|
||||||
|
User user = userMapper.selectOne(wrapper);
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
throw new RuntimeException("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
String newToken = jwtUtil.generateToken(user.getUserId(), user.getUserName());
|
||||||
|
String newRefreshToken = jwtUtil.generateRefreshToken(user.getUserId());
|
||||||
|
|
||||||
|
return new LoginToken(newToken, newRefreshToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.soybean.admin.service;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class PermissionService {
|
||||||
|
// 权限管理现在通过角色表的menus字段实现
|
||||||
|
// 不需要单独的权限服务
|
||||||
|
}
|
||||||
132
backend/src/main/java/com/soybean/admin/service/RoleService.java
Normal file
132
backend/src/main/java/com/soybean/admin/service/RoleService.java
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
package com.soybean.admin.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.soybean.admin.dto.PageRequest;
|
||||||
|
import com.soybean.admin.dto.PageResponse;
|
||||||
|
import com.soybean.admin.dto.RoleDTO;
|
||||||
|
import com.soybean.admin.entity.Role;
|
||||||
|
import com.soybean.admin.mapper.RoleMapper;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class RoleService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RoleMapper roleMapper;
|
||||||
|
|
||||||
|
public PageResponse<RoleDTO> getRoleList(PageRequest request) {
|
||||||
|
Page<Role> page = new Page<>(request.getCurrent(), request.getSize());
|
||||||
|
LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
|
||||||
|
if (StringUtils.hasText(request.getRoleName())) {
|
||||||
|
wrapper.like(Role::getRoleName, request.getRoleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.getStatus() != null) {
|
||||||
|
wrapper.eq(Role::getStatus, request.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper.orderByDesc(Role::getCreateTime);
|
||||||
|
|
||||||
|
IPage<Role> rolePage = roleMapper.selectPage(page, wrapper);
|
||||||
|
|
||||||
|
List<RoleDTO> records = rolePage.getRecords().stream().map(role -> {
|
||||||
|
RoleDTO dto = new RoleDTO();
|
||||||
|
BeanUtils.copyProperties(role, dto);
|
||||||
|
return dto;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
return new PageResponse<>(records, rolePage.getTotal(),
|
||||||
|
request.getCurrent(), request.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RoleDTO> getAllRoles() {
|
||||||
|
LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
// 不过滤状态,返回所有角色
|
||||||
|
wrapper.orderBy(true, true, Role::getCreateTime);
|
||||||
|
|
||||||
|
List<Role> roles = roleMapper.selectList(wrapper);
|
||||||
|
return roles.stream().map(role -> {
|
||||||
|
RoleDTO dto = new RoleDTO();
|
||||||
|
BeanUtils.copyProperties(role, dto);
|
||||||
|
return dto;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleDTO getRoleById(Long id) {
|
||||||
|
Role role = roleMapper.selectById(id);
|
||||||
|
if (role == null) {
|
||||||
|
throw new RuntimeException("角色不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
RoleDTO dto = new RoleDTO();
|
||||||
|
BeanUtils.copyProperties(role, dto);
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createRole(RoleDTO dto) {
|
||||||
|
// 检查角色编码是否已存在
|
||||||
|
LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(Role::getRoleCode, dto.getRoleCode());
|
||||||
|
if (roleMapper.selectCount(wrapper) > 0) {
|
||||||
|
throw new RuntimeException("角色编码已存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
Role role = new Role();
|
||||||
|
BeanUtils.copyProperties(dto, role);
|
||||||
|
role.setCreateTime(LocalDateTime.now());
|
||||||
|
role.setUpdateTime(LocalDateTime.now());
|
||||||
|
role.setDeleted(0);
|
||||||
|
|
||||||
|
if (role.getStatus() == null) {
|
||||||
|
role.setStatus(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
roleMapper.insert(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateRole(RoleDTO dto) {
|
||||||
|
Role existRole = roleMapper.selectById(dto.getId());
|
||||||
|
if (existRole == null) {
|
||||||
|
throw new RuntimeException("角色不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查角色编码是否被其他角色使用
|
||||||
|
LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(Role::getRoleCode, dto.getRoleCode());
|
||||||
|
wrapper.ne(Role::getId, dto.getId());
|
||||||
|
if (roleMapper.selectCount(wrapper) > 0) {
|
||||||
|
throw new RuntimeException("角色编码已被使用");
|
||||||
|
}
|
||||||
|
|
||||||
|
Role role = new Role();
|
||||||
|
BeanUtils.copyProperties(dto, role);
|
||||||
|
role.setUpdateTime(LocalDateTime.now());
|
||||||
|
|
||||||
|
roleMapper.updateById(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteRole(Long id) {
|
||||||
|
Role role = roleMapper.selectById(id);
|
||||||
|
if (role == null) {
|
||||||
|
throw new RuntimeException("角色不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
roleMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void batchDelete(List<Long> ids) {
|
||||||
|
for (Long id : ids) {
|
||||||
|
deleteRole(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,274 @@
|
|||||||
|
package com.soybean.admin.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.soybean.admin.dto.MenuRoute;
|
||||||
|
import com.soybean.admin.dto.UserRoute;
|
||||||
|
import com.soybean.admin.entity.Role;
|
||||||
|
import com.soybean.admin.entity.Route;
|
||||||
|
import com.soybean.admin.entity.User;
|
||||||
|
import com.soybean.admin.mapper.RoleMapper;
|
||||||
|
import com.soybean.admin.mapper.RouteMapper;
|
||||||
|
import com.soybean.admin.mapper.UserMapper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class RouteService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RouteMapper routeMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserMapper userMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RoleMapper roleMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
public List<MenuRoute> getConstantRoutes() {
|
||||||
|
LambdaQueryWrapper<Route> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(Route::getStatus, 1)
|
||||||
|
.orderByAsc(Route::getOrderNum);
|
||||||
|
|
||||||
|
List<Route> routes = routeMapper.selectList(wrapper);
|
||||||
|
return convertToMenuRoutes(routes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoute getUserRoutes(String userId) {
|
||||||
|
// 1. 获取用户信息
|
||||||
|
LambdaQueryWrapper<User> userWrapper = new LambdaQueryWrapper<>();
|
||||||
|
userWrapper.eq(User::getUserId, userId);
|
||||||
|
User user = userMapper.selectOne(userWrapper);
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
throw new RuntimeException("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("=== 用户路由权限调试 ===");
|
||||||
|
System.out.println("用户ID: " + userId);
|
||||||
|
System.out.println("用户角色: " + user.getRoles());
|
||||||
|
|
||||||
|
// 2. 获取用户的角色列表
|
||||||
|
Set<String> userRoleCodes = user.getRoles() != null ?
|
||||||
|
new HashSet<>(Arrays.asList(user.getRoles().split(","))) : new HashSet<>();
|
||||||
|
|
||||||
|
if (userRoleCodes.isEmpty()) {
|
||||||
|
System.out.println("用户没有角色,返回空路由");
|
||||||
|
// 如果用户没有角色,返回空路由
|
||||||
|
return new UserRoute(new ArrayList<>(), "home");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 查询用户角色配置的菜单权限
|
||||||
|
LambdaQueryWrapper<Role> roleWrapper = new LambdaQueryWrapper<>();
|
||||||
|
roleWrapper.in(Role::getRoleCode, userRoleCodes)
|
||||||
|
.eq(Role::getStatus, 1);
|
||||||
|
List<Role> roles = roleMapper.selectList(roleWrapper);
|
||||||
|
|
||||||
|
System.out.println("查询到的角色数量: " + roles.size());
|
||||||
|
|
||||||
|
// 4. 收集所有角色配置的菜单名称
|
||||||
|
Set<String> allowedMenus = new HashSet<>();
|
||||||
|
for (Role role : roles) {
|
||||||
|
System.out.println("角色: " + role.getRoleCode() + " - " + role.getRoleName());
|
||||||
|
System.out.println("配置的菜单: " + role.getMenus());
|
||||||
|
|
||||||
|
if (role.getMenus() != null && !role.getMenus().isEmpty()) {
|
||||||
|
String[] menus = role.getMenus().split(",");
|
||||||
|
for (String menu : menus) {
|
||||||
|
if (menu != null && !menu.trim().isEmpty()) {
|
||||||
|
String trimmedMenu = menu.trim();
|
||||||
|
allowedMenus.add(trimmedMenu);
|
||||||
|
|
||||||
|
// 如果是子菜单,自动添加父菜单
|
||||||
|
if (trimmedMenu.contains("_")) {
|
||||||
|
String parentMenu = trimmedMenu.substring(0, trimmedMenu.lastIndexOf("_"));
|
||||||
|
allowedMenus.add(parentMenu);
|
||||||
|
System.out.println("自动添加父菜单: " + parentMenu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("允许访问的菜单: " + allowedMenus);
|
||||||
|
|
||||||
|
// 5. 如果角色没有配置任何菜单,返回空路由
|
||||||
|
if (allowedMenus.isEmpty()) {
|
||||||
|
System.out.println("角色没有配置菜单,返回空路由");
|
||||||
|
return new UserRoute(new ArrayList<>(), "home");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 获取所有启用的路由
|
||||||
|
LambdaQueryWrapper<Route> routeWrapper = new LambdaQueryWrapper<>();
|
||||||
|
routeWrapper.eq(Route::getStatus, 1)
|
||||||
|
.orderByAsc(Route::getOrderNum);
|
||||||
|
List<Route> allRoutes = routeMapper.selectList(routeWrapper);
|
||||||
|
|
||||||
|
System.out.println("数据库中的路由总数: " + allRoutes.size());
|
||||||
|
|
||||||
|
// 7. 根据角色配置的菜单过滤路由,排除 home(home 是常量路由,由前端管理)
|
||||||
|
List<Route> filteredRoutes = allRoutes.stream()
|
||||||
|
.filter(route -> {
|
||||||
|
// 排除 home 路由,它应该由前端的 constantRoutes 管理
|
||||||
|
if ("home".equals(route.getName())) {
|
||||||
|
System.out.println("路由: " + route.getName() + " - 跳过(常量路由)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean allowed = allowedMenus.contains(route.getName());
|
||||||
|
System.out.println("路由: " + route.getName() + " - 是否允许: " + allowed);
|
||||||
|
return allowed;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
System.out.println("过滤后的路由数量: " + filteredRoutes.size());
|
||||||
|
|
||||||
|
// 8. 转换为菜单路由并返回
|
||||||
|
List<MenuRoute> menuRoutes = convertToMenuRoutes(filteredRoutes);
|
||||||
|
|
||||||
|
System.out.println("最终返回的路由数量: " + menuRoutes.size());
|
||||||
|
for (MenuRoute route : menuRoutes) {
|
||||||
|
System.out.println("根路由: " + route.getName() +
|
||||||
|
" - 子路由数: " + (route.getChildren() != null ? route.getChildren().size() : 0));
|
||||||
|
if (route.getChildren() != null) {
|
||||||
|
for (MenuRoute child : route.getChildren()) {
|
||||||
|
System.out.println(" 子路由: " + child.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("=== 调试结束 ===");
|
||||||
|
|
||||||
|
return new UserRoute(menuRoutes, "home");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRouteExist(String routeName) {
|
||||||
|
LambdaQueryWrapper<Route> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(Route::getName, routeName)
|
||||||
|
.eq(Route::getStatus, 1);
|
||||||
|
return routeMapper.selectCount(wrapper) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<MenuRoute> convertToMenuRoutes(List<Route> routes) {
|
||||||
|
System.out.println("=== 开始构建路由树 ===");
|
||||||
|
System.out.println("输入路由数量: " + routes.size());
|
||||||
|
|
||||||
|
// 先转换所有路由为 MenuRoute
|
||||||
|
List<MenuRoute> allMenuRoutes = routes.stream().map(route -> {
|
||||||
|
MenuRoute menuRoute = new MenuRoute();
|
||||||
|
menuRoute.setId(route.getRouteId());
|
||||||
|
menuRoute.setName(route.getName());
|
||||||
|
menuRoute.setPath(route.getPath());
|
||||||
|
menuRoute.setComponent(route.getComponent());
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (route.getMeta() != null && !route.getMeta().isEmpty()) {
|
||||||
|
Map<String, Object> meta = objectMapper.readValue(
|
||||||
|
route.getMeta(),
|
||||||
|
new TypeReference<Map<String, Object>>() {}
|
||||||
|
);
|
||||||
|
menuRoute.setMeta(meta);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
menuRoute.setMeta(new HashMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
return menuRoute;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 构建父子关系
|
||||||
|
Map<String, MenuRoute> routeMap = new HashMap<>();
|
||||||
|
Set<String> childRouteNames = new HashSet<>(); // 记录所有子路由的名称
|
||||||
|
|
||||||
|
// 第一遍:将所有路由放入 map
|
||||||
|
for (MenuRoute menuRoute : allMenuRoutes) {
|
||||||
|
routeMap.put(menuRoute.getName(), menuRoute);
|
||||||
|
menuRoute.setChildren(new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第二遍:根据 path 识别父子关系
|
||||||
|
for (MenuRoute menuRoute : allMenuRoutes) {
|
||||||
|
String path = menuRoute.getPath();
|
||||||
|
String name = menuRoute.getName();
|
||||||
|
|
||||||
|
// 计算路径中的斜杠数量
|
||||||
|
int slashCount = path.length() - path.replace("/", "").length();
|
||||||
|
|
||||||
|
// 如果路径有2个或以上斜杠(如 /device/list),说明是子路由
|
||||||
|
if (slashCount >= 2) {
|
||||||
|
childRouteNames.add(name);
|
||||||
|
System.out.println("识别子路由: " + name + " (path: " + path + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第三遍:建立父子关系
|
||||||
|
for (MenuRoute menuRoute : allMenuRoutes) {
|
||||||
|
String path = menuRoute.getPath();
|
||||||
|
String name = menuRoute.getName();
|
||||||
|
int slashCount = path.length() - path.replace("/", "").length();
|
||||||
|
|
||||||
|
// 如果路径有2个或以上斜杠,说明是子路由
|
||||||
|
if (slashCount >= 2) {
|
||||||
|
// 从路径中提取父路径(如 /device/list -> /device)
|
||||||
|
String parentPath = path.substring(0, path.lastIndexOf("/"));
|
||||||
|
|
||||||
|
// 查找父路由
|
||||||
|
MenuRoute parent = null;
|
||||||
|
for (MenuRoute route : allMenuRoutes) {
|
||||||
|
if (route.getPath().equals(parentPath)) {
|
||||||
|
parent = route;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent != null) {
|
||||||
|
parent.getChildren().add(menuRoute);
|
||||||
|
System.out.println("添加子路由: " + name + " -> 父路由: " + parent.getName());
|
||||||
|
} else {
|
||||||
|
System.out.println("警告:找不到父路由 (path: " + parentPath + ") for " + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第四遍:只将非子路由添加到根路由列表
|
||||||
|
List<MenuRoute> rootRoutes = new ArrayList<>();
|
||||||
|
for (MenuRoute menuRoute : allMenuRoutes) {
|
||||||
|
if (!childRouteNames.contains(menuRoute.getName())) {
|
||||||
|
rootRoutes.add(menuRoute);
|
||||||
|
System.out.println("添加根路由: " + menuRoute.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理空的 children 列表
|
||||||
|
cleanEmptyChildren(rootRoutes);
|
||||||
|
|
||||||
|
System.out.println("=== 路由树构建完成 ===");
|
||||||
|
System.out.println("最终返回的根路由数量: " + rootRoutes.size());
|
||||||
|
for (MenuRoute route : rootRoutes) {
|
||||||
|
System.out.println("根路由: " + route.getName() +
|
||||||
|
" - 子路由数: " + (route.getChildren() != null ? route.getChildren().size() : 0));
|
||||||
|
if (route.getChildren() != null) {
|
||||||
|
for (MenuRoute child : route.getChildren()) {
|
||||||
|
System.out.println(" 子路由: " + child.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rootRoutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanEmptyChildren(List<MenuRoute> routes) {
|
||||||
|
for (MenuRoute route : routes) {
|
||||||
|
if (route.getChildren() != null && route.getChildren().isEmpty()) {
|
||||||
|
route.setChildren(null);
|
||||||
|
} else if (route.getChildren() != null) {
|
||||||
|
cleanEmptyChildren(route.getChildren());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
140
backend/src/main/java/com/soybean/admin/service/UserService.java
Normal file
140
backend/src/main/java/com/soybean/admin/service/UserService.java
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
package com.soybean.admin.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.soybean.admin.dto.PageRequest;
|
||||||
|
import com.soybean.admin.dto.PageResponse;
|
||||||
|
import com.soybean.admin.dto.UserDTO;
|
||||||
|
import com.soybean.admin.entity.User;
|
||||||
|
import com.soybean.admin.mapper.UserMapper;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserMapper userMapper;
|
||||||
|
|
||||||
|
public PageResponse<UserDTO> getUserList(PageRequest request) {
|
||||||
|
Page<User> page = new Page<>(request.getCurrent(), request.getSize());
|
||||||
|
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
|
||||||
|
// 排除 admin 账号
|
||||||
|
wrapper.ne(User::getUserName, "admin");
|
||||||
|
|
||||||
|
if (StringUtils.hasText(request.getUserName())) {
|
||||||
|
wrapper.like(User::getUserName, request.getUserName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.getStatus() != null) {
|
||||||
|
wrapper.eq(User::getStatus, request.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper.orderByDesc(User::getCreateTime);
|
||||||
|
|
||||||
|
IPage<User> userPage = userMapper.selectPage(page, wrapper);
|
||||||
|
|
||||||
|
List<UserDTO> records = userPage.getRecords().stream().map(user -> {
|
||||||
|
UserDTO dto = new UserDTO();
|
||||||
|
BeanUtils.copyProperties(user, dto);
|
||||||
|
dto.setPassword(null); // 不返回密码
|
||||||
|
return dto;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
return new PageResponse<>(records, userPage.getTotal(),
|
||||||
|
request.getCurrent(), request.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserDTO getUserById(Long id) {
|
||||||
|
User user = userMapper.selectById(id);
|
||||||
|
if (user == null) {
|
||||||
|
throw new RuntimeException("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("admin".equals(user.getUserName())) {
|
||||||
|
throw new RuntimeException("无法操作管理员账号");
|
||||||
|
}
|
||||||
|
|
||||||
|
UserDTO dto = new UserDTO();
|
||||||
|
BeanUtils.copyProperties(user, dto);
|
||||||
|
dto.setPassword(null);
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createUser(UserDTO dto) {
|
||||||
|
// 检查用户名是否已存在
|
||||||
|
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(User::getUserName, dto.getUserName());
|
||||||
|
if (userMapper.selectCount(wrapper) > 0) {
|
||||||
|
throw new RuntimeException("用户名已存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查用户ID是否已存在
|
||||||
|
wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(User::getUserId, dto.getUserId());
|
||||||
|
if (userMapper.selectCount(wrapper) > 0) {
|
||||||
|
throw new RuntimeException("用户ID已存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = new User();
|
||||||
|
BeanUtils.copyProperties(dto, user);
|
||||||
|
user.setCreateTime(LocalDateTime.now());
|
||||||
|
user.setUpdateTime(LocalDateTime.now());
|
||||||
|
user.setDeleted(0);
|
||||||
|
|
||||||
|
if (user.getStatus() == null) {
|
||||||
|
user.setStatus(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
userMapper.insert(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateUser(UserDTO dto) {
|
||||||
|
User existUser = userMapper.selectById(dto.getId());
|
||||||
|
if (existUser == null) {
|
||||||
|
throw new RuntimeException("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("admin".equals(existUser.getUserName())) {
|
||||||
|
throw new RuntimeException("无法修改管理员账号");
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = new User();
|
||||||
|
BeanUtils.copyProperties(dto, user);
|
||||||
|
user.setUpdateTime(LocalDateTime.now());
|
||||||
|
|
||||||
|
// 如果没有提供密码,则不更新密码
|
||||||
|
if (!StringUtils.hasText(dto.getPassword())) {
|
||||||
|
user.setPassword(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
userMapper.updateById(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteUser(Long id) {
|
||||||
|
User user = userMapper.selectById(id);
|
||||||
|
if (user == null) {
|
||||||
|
throw new RuntimeException("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("admin".equals(user.getUserName())) {
|
||||||
|
throw new RuntimeException("无法删除管理员账号");
|
||||||
|
}
|
||||||
|
|
||||||
|
userMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void batchDelete(List<Long> ids) {
|
||||||
|
for (Long id : ids) {
|
||||||
|
deleteUser(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
88
backend/src/main/java/com/soybean/admin/util/JwtUtil.java
Normal file
88
backend/src/main/java/com/soybean/admin/util/JwtUtil.java
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package com.soybean.admin.util;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JwtUtil {
|
||||||
|
|
||||||
|
@Value("${jwt.secret}")
|
||||||
|
private String secret;
|
||||||
|
|
||||||
|
@Value("${jwt.expiration}")
|
||||||
|
private Long expiration;
|
||||||
|
|
||||||
|
@Value("${jwt.refresh-expiration}")
|
||||||
|
private Long refreshExpiration;
|
||||||
|
|
||||||
|
private SecretKey getSignKey() {
|
||||||
|
return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateToken(String userId, String userName) {
|
||||||
|
Map<String, Object> claims = new HashMap<>();
|
||||||
|
claims.put("userId", userId);
|
||||||
|
claims.put("userName", userName);
|
||||||
|
return createToken(claims, userId, expiration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateRefreshToken(String userId) {
|
||||||
|
Map<String, Object> claims = new HashMap<>();
|
||||||
|
claims.put("userId", userId);
|
||||||
|
return createToken(claims, userId, refreshExpiration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createToken(Map<String, Object> claims, String subject, Long expiration) {
|
||||||
|
Date now = new Date();
|
||||||
|
Date expiryDate = new Date(now.getTime() + expiration);
|
||||||
|
|
||||||
|
return Jwts.builder()
|
||||||
|
.setClaims(claims)
|
||||||
|
.setSubject(subject)
|
||||||
|
.setIssuedAt(now)
|
||||||
|
.setExpiration(expiryDate)
|
||||||
|
.signWith(getSignKey(), SignatureAlgorithm.HS256)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Claims parseToken(String token) {
|
||||||
|
return Jwts.parserBuilder()
|
||||||
|
.setSigningKey(getSignKey())
|
||||||
|
.build()
|
||||||
|
.parseClaimsJws(token)
|
||||||
|
.getBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserIdFromToken(String token) {
|
||||||
|
Claims claims = parseToken(token);
|
||||||
|
return claims.get("userId", String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTokenExpired(String token) {
|
||||||
|
try {
|
||||||
|
Claims claims = parseToken(token);
|
||||||
|
return claims.getExpiration().before(new Date());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean validateToken(String token) {
|
||||||
|
try {
|
||||||
|
parseToken(token);
|
||||||
|
return !isTokenExpired(token);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
backend/src/main/resources/application.yml
Normal file
32
backend/src/main/resources/application.yml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: soybean-admin-backend
|
||||||
|
|
||||||
|
datasource:
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
url: jdbc:mysql://localhost:3306/soybean_admin?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
|
||||||
|
username: root
|
||||||
|
password: root
|
||||||
|
|
||||||
|
jackson:
|
||||||
|
time-zone: GMT+8
|
||||||
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
|
|
||||||
|
server:
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
mybatis-plus:
|
||||||
|
configuration:
|
||||||
|
map-underscore-to-camel-case: true
|
||||||
|
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||||
|
global-config:
|
||||||
|
db-config:
|
||||||
|
id-type: auto
|
||||||
|
logic-delete-field: deleted
|
||||||
|
logic-delete-value: 1
|
||||||
|
logic-not-delete-value: 0
|
||||||
|
|
||||||
|
jwt:
|
||||||
|
secret: soybean-admin-secret-key-2024-spring-boot-jwt-token
|
||||||
|
expiration: 7200000
|
||||||
|
refresh-expiration: 604800000
|
||||||
156
backend/src/main/resources/sql/add_all_routes.sql
Normal file
156
backend/src/main/resources/sql/add_all_routes.sql
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
-- 添加所有菜单路由
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
-- 清理旧数据(保留home)
|
||||||
|
DELETE FROM sys_route WHERE route_id NOT IN ('1');
|
||||||
|
|
||||||
|
-- 管理员菜单
|
||||||
|
-- 1. 首页 (已存在)
|
||||||
|
|
||||||
|
-- 2. 设备管理
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('device', 'device', '/device', 'layout.base$view.device',
|
||||||
|
'{"title":"设备管理","i18nKey":"route.device","icon":"mdi:desktop-classic","order":2}',
|
||||||
|
'R_SUPER,R_ADMIN', 2, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('device_list', 'device_list', '/device/list', 'layout.base$view.device_list',
|
||||||
|
'{"title":"设备列表","i18nKey":"route.device_list","icon":"mdi:format-list-bulleted","order":1}',
|
||||||
|
'R_SUPER,R_ADMIN', 2.1, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('device_online', 'device_online', '/device/online', 'layout.base$view.device_online',
|
||||||
|
'{"title":"在线状态","i18nKey":"route.device_online","icon":"mdi:lan-connect","order":2}',
|
||||||
|
'R_SUPER,R_ADMIN', 2.2, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('device_power', 'device_power', '/device/power', 'layout.base$view.device_power',
|
||||||
|
'{"title":"电源管理","i18nKey":"route.device_power","icon":"mdi:power","order":3}',
|
||||||
|
'R_SUPER,R_ADMIN', 2.3, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('device_monitor', 'device_monitor', '/device/monitor', 'layout.base$view.device_monitor',
|
||||||
|
'{"title":"远程监控","i18nKey":"route.device_monitor","icon":"mdi:monitor-eye","order":4}',
|
||||||
|
'R_SUPER,R_ADMIN', 2.4, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('device_group', 'device_group', '/device/group', 'layout.base$view.device_group',
|
||||||
|
'{"title":"设备分组","i18nKey":"route.device_group","icon":"mdi:group","order":5}',
|
||||||
|
'R_SUPER,R_ADMIN', 2.5, 1);
|
||||||
|
|
||||||
|
-- 3. 屏幕监控
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('screen', 'screen', '/screen', 'layout.base$view.screen',
|
||||||
|
'{"title":"屏幕监控","i18nKey":"route.screen","icon":"mdi:monitor-screenshot","order":3}',
|
||||||
|
'R_SUPER,R_ADMIN', 3, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('screen_wall', 'screen_wall', '/screen/wall', 'layout.base$view.screen_wall',
|
||||||
|
'{"title":"监控墙","i18nKey":"route.screen_wall","icon":"mdi:view-grid","order":1}',
|
||||||
|
'R_SUPER,R_ADMIN', 3.1, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('screen_control', 'screen_control', '/screen/control', 'layout.base$view.screen_control',
|
||||||
|
'{"title":"单屏控制","i18nKey":"route.screen_control","icon":"mdi:cursor-default-click","order":2}',
|
||||||
|
'R_SUPER,R_ADMIN', 3.2, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('screen_record', 'screen_record', '/screen/record', 'layout.base$view.screen_record',
|
||||||
|
'{"title":"控制记录","i18nKey":"route.screen_record","icon":"mdi:history","order":3}',
|
||||||
|
'R_SUPER,R_ADMIN', 3.3, 1);
|
||||||
|
|
||||||
|
-- 4. 用户管理
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('user_manage', 'user-manage', '/user-manage', 'layout.base$view.user-manage',
|
||||||
|
'{"title":"用户管理","i18nKey":"route.user-manage","icon":"mdi:account-group","order":4}',
|
||||||
|
'R_SUPER,R_ADMIN', 4, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('user_list', 'user_list', '/user-manage/list', 'layout.base$view.user-manage_list',
|
||||||
|
'{"title":"用户列表","i18nKey":"route.user_list","icon":"mdi:account-multiple","order":1}',
|
||||||
|
'R_SUPER,R_ADMIN', 4.1, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('user_role', 'user_role', '/user-manage/role', 'layout.base$view.user-manage_role',
|
||||||
|
'{"title":"角色管理","i18nKey":"route.user_role","icon":"mdi:shield-account","order":2}',
|
||||||
|
'R_SUPER,R_ADMIN', 4.2, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('user_permission', 'user_permission', '/user-manage/permission', 'layout.base$view.user-manage_permission',
|
||||||
|
'{"title":"权限管理","i18nKey":"route.user_permission","icon":"mdi:key","order":3}',
|
||||||
|
'R_SUPER', 4.3, 1);
|
||||||
|
|
||||||
|
-- 5. 申请管理
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('application', 'application', '/application', 'layout.base$view.application',
|
||||||
|
'{"title":"使用申请","i18nKey":"route.application","icon":"mdi:file-document-edit","order":5}',
|
||||||
|
'R_SUPER,R_ADMIN', 5, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('application_approval', 'application_approval', '/application/approval', 'layout.base$view.application_approval',
|
||||||
|
'{"title":"申请审批","i18nKey":"route.application_approval","icon":"mdi:clipboard-check","order":1}',
|
||||||
|
'R_SUPER,R_ADMIN', 5.1, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('application_history', 'application_history', '/application/history', 'layout.base$view.application_history',
|
||||||
|
'{"title":"使用记录","i18nKey":"route.application_history","icon":"mdi:history","order":2}',
|
||||||
|
'R_SUPER,R_ADMIN', 5.2, 1);
|
||||||
|
|
||||||
|
-- 6. 系统设置
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('system', 'system', '/system', 'layout.base$view.system',
|
||||||
|
'{"title":"系统设置","i18nKey":"route.system","icon":"mdi:cog","order":6}',
|
||||||
|
'R_SUPER', 6, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('system_amt', 'system_amt', '/system/amt', 'layout.base$view.system_amt',
|
||||||
|
'{"title":"AMT设置","i18nKey":"route.system_amt","icon":"mdi:chip","order":1}',
|
||||||
|
'R_SUPER', 6.1, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('system_agent', 'system_agent', '/system/agent', 'layout.base$view.system_agent',
|
||||||
|
'{"title":"Agent设置","i18nKey":"route.system_agent","icon":"mdi:application-cog","order":2}',
|
||||||
|
'R_SUPER', 6.2, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('system_log', 'system_log', '/system/log', 'layout.base$view.system_log',
|
||||||
|
'{"title":"日志中心","i18nKey":"route.system_log","icon":"mdi:text-box-multiple","order":3}',
|
||||||
|
'R_SUPER', 6.3, 1);
|
||||||
|
|
||||||
|
-- 普通用户菜单
|
||||||
|
-- 7. 我的设备
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('my_device', 'my-device', '/my-device', 'layout.base$view.my-device',
|
||||||
|
'{"title":"我的设备","i18nKey":"route.my_device","icon":"mdi:laptop","order":7}',
|
||||||
|
'R_USER', 7, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('my_device_status', 'my_device_status', '/my-device/status', 'layout.base$view.my-device_status',
|
||||||
|
'{"title":"设备状态","i18nKey":"route.my_device_status","icon":"mdi:information","order":1}',
|
||||||
|
'R_USER', 7.1, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('my_device_power', 'my_device_power', '/my-device/power-control', 'layout.base$view.my-device_power-control',
|
||||||
|
'{"title":"电源控制","i18nKey":"route.my_device_power","icon":"mdi:power-settings","order":2}',
|
||||||
|
'R_USER', 7.2, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('my_device_remote', 'my_device_remote', '/my-device/remote-control', 'layout.base$view.my-device_remote-control',
|
||||||
|
'{"title":"远程控制","i18nKey":"route.my_device_remote","icon":"mdi:remote-desktop","order":3}',
|
||||||
|
'R_USER', 7.3, 1);
|
||||||
|
|
||||||
|
-- 8. 设备申请
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('my_application', 'my-application', '/my-application', 'layout.base$view.my-application',
|
||||||
|
'{"title":"设备申请","i18nKey":"route.my_application","icon":"mdi:file-document","order":8}',
|
||||||
|
'R_USER', 8, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('my_application_apply', 'my_application_apply', '/my-application/apply', 'layout.base$view.my-application_apply',
|
||||||
|
'{"title":"申请使用","i18nKey":"route.my_application_apply","icon":"mdi:file-plus","order":1}',
|
||||||
|
'R_USER', 8.1, 1);
|
||||||
|
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('my_application_list', 'my_application_list', '/my-application/my-list', 'layout.base$view.my-application_my-list',
|
||||||
|
'{"title":"我的申请","i18nKey":"route.my_application_list","icon":"mdi:format-list-checks","order":2}',
|
||||||
|
'R_USER', 8.2, 1);
|
||||||
22
backend/src/main/resources/sql/add_role_table.sql
Normal file
22
backend/src/main/resources/sql/add_role_table.sql
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
-- 角色表
|
||||||
|
CREATE TABLE IF NOT EXISTS sys_role (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
|
||||||
|
role_code VARCHAR(50) NOT NULL UNIQUE COMMENT '角色编码',
|
||||||
|
role_name VARCHAR(50) NOT NULL COMMENT '角色名称',
|
||||||
|
description VARCHAR(200) COMMENT '角色描述',
|
||||||
|
menus TEXT COMMENT '可访问菜单列表,逗号分隔',
|
||||||
|
status INT DEFAULT 1 COMMENT '状态:1-启用,2-禁用',
|
||||||
|
deleted INT DEFAULT 0 COMMENT '删除标记:0-未删除,1-已删除',
|
||||||
|
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
INDEX idx_role_code (role_code),
|
||||||
|
INDEX idx_status (status)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
|
||||||
|
|
||||||
|
-- 插入默认角色
|
||||||
|
INSERT INTO sys_role (role_code, role_name, description, menus, status) VALUES
|
||||||
|
('R_SUPER', '超级管理员', '拥有系统所有权限', NULL, 1),
|
||||||
|
('R_ADMIN', '管理员', '拥有管理权限', NULL, 1),
|
||||||
|
('R_USER', '普通用户', '普通用户权限', NULL, 1);
|
||||||
11
backend/src/main/resources/sql/add_user_route.sql
Normal file
11
backend/src/main/resources/sql/add_user_route.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
-- 添加用户管理路由
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
-- 先删除可能存在的旧记录
|
||||||
|
DELETE FROM sys_route WHERE route_id = 'user_manage';
|
||||||
|
|
||||||
|
-- 插入用户管理路由,order_num 设置为 1.5,这样会排在 home(order=1) 后面
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('user_manage', 'user-manage', '/user-manage', 'layout.base$view.user-manage',
|
||||||
|
'{"title":"用户管理","i18nKey":"route.user-manage","icon":"mdi:account-group","order":1.5}',
|
||||||
|
'R_SUPER,R_ADMIN', 1.5, 1);
|
||||||
22
backend/src/main/resources/sql/fix_component_names.sql
Normal file
22
backend/src/main/resources/sql/fix_component_names.sql
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
-- 修复 component 字段,确保组件路径与实际文件夹结构一致(使用连字符)
|
||||||
|
-- 注意:路由名称(name)使用下划线,但组件路径(component)必须使用连字符匹配实际文件夹
|
||||||
|
|
||||||
|
-- 修复 user-manage 相关组件(文件夹是 user-manage)
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.user-manage' WHERE name = 'user_manage';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.user-manage_list' WHERE name = 'user_manage_list';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.user-manage_role' WHERE name = 'user_manage_role';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.user-manage_permission' WHERE name = 'user_manage_permission';
|
||||||
|
|
||||||
|
-- 修复 my-device 相关组件(文件夹是 my-device)
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-device' WHERE name = 'my_device';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-device_status' WHERE name = 'my_device_status';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-device_power-control' WHERE name = 'my_device_power';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-device_remote-control' WHERE name = 'my_device_remote';
|
||||||
|
|
||||||
|
-- 修复 my-application 相关组件(文件夹是 my-application)
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-application' WHERE name = 'my_application';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-application_apply' WHERE name = 'my_application_apply';
|
||||||
|
UPDATE sys_route SET component = 'layout.base$view.my-application_my-list' WHERE name = 'my_application_list';
|
||||||
|
|
||||||
|
-- 查看修复结果
|
||||||
|
SELECT name, path, component FROM sys_route WHERE name LIKE '%user%' OR name LIKE '%my_%' ORDER BY name;
|
||||||
19
backend/src/main/resources/sql/fix_route_names.sql
Normal file
19
backend/src/main/resources/sql/fix_route_names.sql
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-- 修复路由名称,统一使用下划线而不是连字符
|
||||||
|
-- 这样父子路由才能正确匹配
|
||||||
|
|
||||||
|
-- 修复 user-manage 相关路由
|
||||||
|
UPDATE sys_route SET name = 'user_manage' WHERE name = 'user-manage';
|
||||||
|
UPDATE sys_route SET name = 'user_manage_list' WHERE name = 'user_list';
|
||||||
|
UPDATE sys_route SET name = 'user_manage_role' WHERE name = 'user_role';
|
||||||
|
UPDATE sys_route SET name = 'user_manage_permission' WHERE name = 'user_permission';
|
||||||
|
|
||||||
|
-- 修复 my-device 相关路由
|
||||||
|
UPDATE sys_route SET name = 'my_device' WHERE name = 'my-device';
|
||||||
|
-- my_device 的子路由已经是正确的格式了
|
||||||
|
|
||||||
|
-- 修复 my-application 相关路由
|
||||||
|
UPDATE sys_route SET name = 'my_application' WHERE name = 'my-application';
|
||||||
|
-- my_application 的子路由已经是正确的格式了
|
||||||
|
|
||||||
|
-- 查看修复结果
|
||||||
|
SELECT id, name, path FROM sys_route WHERE name LIKE '%user%' OR name LIKE '%my_%' ORDER BY name;
|
||||||
64
backend/src/main/resources/sql/init.sql
Normal file
64
backend/src/main/resources/sql/init.sql
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
-- 创建数据库
|
||||||
|
CREATE DATABASE IF NOT EXISTS soybean_admin DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
-- 用户表
|
||||||
|
CREATE TABLE IF NOT EXISTS sys_user (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
|
||||||
|
user_id VARCHAR(50) NOT NULL UNIQUE COMMENT '用户ID',
|
||||||
|
user_name VARCHAR(50) NOT NULL COMMENT '用户名',
|
||||||
|
password VARCHAR(100) NOT NULL COMMENT '密码',
|
||||||
|
roles VARCHAR(200) COMMENT '角色列表,逗号分隔',
|
||||||
|
buttons VARCHAR(500) COMMENT '按钮权限列表,逗号分隔',
|
||||||
|
status INT DEFAULT 1 COMMENT '状态:1-启用,2-禁用',
|
||||||
|
deleted INT DEFAULT 0 COMMENT '删除标记:0-未删除,1-已删除',
|
||||||
|
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
INDEX idx_user_name (user_name),
|
||||||
|
INDEX idx_user_id (user_id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
|
||||||
|
|
||||||
|
-- 路由表
|
||||||
|
CREATE TABLE IF NOT EXISTS sys_route (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
|
||||||
|
route_id VARCHAR(50) NOT NULL UNIQUE COMMENT '路由ID',
|
||||||
|
name VARCHAR(50) NOT NULL COMMENT '路由名称',
|
||||||
|
path VARCHAR(200) NOT NULL COMMENT '路由路径',
|
||||||
|
component VARCHAR(200) COMMENT '组件路径',
|
||||||
|
meta TEXT COMMENT '路由元信息JSON',
|
||||||
|
roles VARCHAR(200) COMMENT '可访问角色,逗号分隔',
|
||||||
|
order_num INT DEFAULT 0 COMMENT '排序号',
|
||||||
|
status INT DEFAULT 1 COMMENT '状态:1-启用,2-禁用',
|
||||||
|
deleted INT DEFAULT 0 COMMENT '删除标记:0-未删除,1-已删除',
|
||||||
|
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
INDEX idx_name (name),
|
||||||
|
INDEX idx_status (status)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='路由表';
|
||||||
|
|
||||||
|
-- 插入默认管理员用户 (密码: admin123)
|
||||||
|
INSERT INTO sys_user (user_id, user_name, password, roles, buttons, status)
|
||||||
|
VALUES ('1', 'admin', 'admin123', 'R_SUPER,R_ADMIN', 'B_ADD,B_EDIT,B_DELETE', 1);
|
||||||
|
|
||||||
|
-- 插入普通用户 (密码: user123)
|
||||||
|
INSERT INTO sys_user (user_id, user_name, password, roles, buttons, status)
|
||||||
|
VALUES ('2', 'user', 'user123', 'R_USER', 'B_VIEW', 1);
|
||||||
|
|
||||||
|
-- 插入默认路由
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('1', 'home', '/home', 'layout.base$view.home',
|
||||||
|
'{"title":"首页","i18nKey":"route.home","icon":"mdi:monitor-dashboard","order":1}',
|
||||||
|
NULL, 1, 1);
|
||||||
|
|
||||||
|
-- 插入示例路由(用户管理)
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('2', 'user', '/user', 'layout.base$view.user',
|
||||||
|
'{"title":"用户管理","i18nKey":"route.user","icon":"mdi:account-group","order":2}',
|
||||||
|
'R_SUPER,R_ADMIN', 2, 1);
|
||||||
|
|
||||||
|
-- 插入示例路由(系统设置)
|
||||||
|
INSERT INTO sys_route (route_id, name, path, component, meta, roles, order_num, status) VALUES
|
||||||
|
('3', 'system', '/system', 'layout.base$view.system',
|
||||||
|
'{"title":"系统设置","i18nKey":"route.system","icon":"mdi:cog","order":3}',
|
||||||
|
'R_SUPER', 3, 1);
|
||||||
20
backend/src/main/resources/sql/init_role_menus.sql
Normal file
20
backend/src/main/resources/sql/init_role_menus.sql
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
-- 初始化角色的菜单权限
|
||||||
|
-- 这个脚本会为现有的角色配置默认的菜单权限
|
||||||
|
|
||||||
|
-- 为超级管理员配置所有菜单
|
||||||
|
UPDATE sys_role
|
||||||
|
SET menus = 'home,user-manage,user-manage_list,user-manage_role,user-manage_permission,device,device_list,device_group,device_monitor,device_online,device_power,screen,screen_wall,screen_control,screen_record,application,application_approval,application_history,my-application,my-application_apply,my-application_my-list,my-device,my-device_status,my-device_remote-control,my-device_power-control,system,system_agent,system_amt,system_log'
|
||||||
|
WHERE role_code = 'R_SUPER';
|
||||||
|
|
||||||
|
-- 为管理员配置大部分菜单(除了系统设置)
|
||||||
|
UPDATE sys_role
|
||||||
|
SET menus = 'home,user-manage,user-manage_list,user-manage_role,user-manage_permission,device,device_list,device_group,device_monitor,device_online,device_power,screen,screen_wall,screen_control,screen_record,application,application_approval,application_history'
|
||||||
|
WHERE role_code = 'R_ADMIN';
|
||||||
|
|
||||||
|
-- 为普通用户配置基本菜单
|
||||||
|
UPDATE sys_role
|
||||||
|
SET menus = 'home,my-application,my-application_apply,my-application_my-list,my-device,my-device_status,my-device_remote-control,my-device_power-control'
|
||||||
|
WHERE role_code = 'R_USER';
|
||||||
|
|
||||||
|
-- 查看更新结果
|
||||||
|
SELECT role_code, role_name, menus FROM sys_role;
|
||||||
14
backend/start.bat
Normal file
14
backend/start.bat
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo Soybean Admin Backend Starting...
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
echo Checking Java version...
|
||||||
|
java -version
|
||||||
|
echo.
|
||||||
|
|
||||||
|
echo Starting Spring Boot application...
|
||||||
|
mvn spring-boot:run
|
||||||
|
|
||||||
|
pause
|
||||||
2
build/config/index.ts
Normal file
2
build/config/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './proxy';
|
||||||
|
export * from './time';
|
||||||
55
build/config/proxy.ts
Normal file
55
build/config/proxy.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import type { ProxyOptions } from 'vite';
|
||||||
|
import { bgRed, bgYellow, green, lightBlue } from 'kolorist';
|
||||||
|
import { consola } from 'consola';
|
||||||
|
import { createServiceConfig } from '../../src/utils/service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set http proxy
|
||||||
|
*
|
||||||
|
* @param env - The current env
|
||||||
|
* @param enable - If enable http proxy
|
||||||
|
*/
|
||||||
|
export function createViteProxy(env: Env.ImportMeta, enable: boolean) {
|
||||||
|
const isEnableHttpProxy = enable && env.VITE_HTTP_PROXY === 'Y';
|
||||||
|
|
||||||
|
if (!isEnableHttpProxy) return undefined;
|
||||||
|
|
||||||
|
const isEnableProxyLog = env.VITE_PROXY_LOG === 'Y';
|
||||||
|
|
||||||
|
const { baseURL, proxyPattern, other } = createServiceConfig(env);
|
||||||
|
|
||||||
|
const proxy: Record<string, ProxyOptions> = createProxyItem({ baseURL, proxyPattern }, isEnableProxyLog);
|
||||||
|
|
||||||
|
other.forEach(item => {
|
||||||
|
Object.assign(proxy, createProxyItem(item, isEnableProxyLog));
|
||||||
|
});
|
||||||
|
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createProxyItem(item: App.Service.ServiceConfigItem, enableLog: boolean) {
|
||||||
|
const proxy: Record<string, ProxyOptions> = {};
|
||||||
|
|
||||||
|
proxy[item.proxyPattern] = {
|
||||||
|
target: item.baseURL,
|
||||||
|
changeOrigin: true,
|
||||||
|
configure: (_proxy, options) => {
|
||||||
|
_proxy.on('proxyReq', (_proxyReq, req, _res) => {
|
||||||
|
if (!enableLog) return;
|
||||||
|
|
||||||
|
const requestUrl = `${lightBlue('[proxy url]')}: ${bgYellow(` ${req.method} `)} ${green(`${item.proxyPattern}${req.url}`)}`;
|
||||||
|
|
||||||
|
const proxyUrl = `${lightBlue('[real request url]')}: ${green(`${options.target}${req.url}`)}`;
|
||||||
|
|
||||||
|
consola.log(`${requestUrl}\n${proxyUrl}`);
|
||||||
|
});
|
||||||
|
_proxy.on('error', (_err, req, _res) => {
|
||||||
|
if (!enableLog) return;
|
||||||
|
consola.log(bgRed(`Error: ${req.method} `), green(`${options.target}${req.url}`));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
rewrite: path => path.replace(new RegExp(`^${item.proxyPattern}`), '')
|
||||||
|
};
|
||||||
|
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
12
build/config/time.ts
Normal file
12
build/config/time.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import dayjs from 'dayjs';
|
||||||
|
import utc from 'dayjs/plugin/utc';
|
||||||
|
import timezone from 'dayjs/plugin/timezone';
|
||||||
|
|
||||||
|
export function getBuildTime() {
|
||||||
|
dayjs.extend(utc);
|
||||||
|
dayjs.extend(timezone);
|
||||||
|
|
||||||
|
const buildTime = dayjs.tz(Date.now(), 'Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss');
|
||||||
|
|
||||||
|
return buildTime;
|
||||||
|
}
|
||||||
9
build/plugins/devtools.ts
Normal file
9
build/plugins/devtools.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import VueDevtools from 'vite-plugin-vue-devtools';
|
||||||
|
|
||||||
|
export function setupDevtoolsPlugin(viteEnv: Env.ImportMeta) {
|
||||||
|
const { VITE_DEVTOOLS_LAUNCH_EDITOR } = viteEnv;
|
||||||
|
|
||||||
|
return VueDevtools({
|
||||||
|
launchEditor: VITE_DEVTOOLS_LAUNCH_EDITOR
|
||||||
|
});
|
||||||
|
}
|
||||||
13
build/plugins/html.ts
Normal file
13
build/plugins/html.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import type { Plugin } from 'vite';
|
||||||
|
|
||||||
|
export function setupHtmlPlugin(buildTime: string) {
|
||||||
|
const plugin: Plugin = {
|
||||||
|
name: 'html-plugin',
|
||||||
|
apply: 'build',
|
||||||
|
transformIndexHtml(html) {
|
||||||
|
return html.replace('<head>', `<head>\n <meta name="buildTime" content="${buildTime}">`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
24
build/plugins/index.ts
Normal file
24
build/plugins/index.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import type { PluginOption } from 'vite';
|
||||||
|
import vue from '@vitejs/plugin-vue';
|
||||||
|
import vueJsx from '@vitejs/plugin-vue-jsx';
|
||||||
|
import progress from 'vite-plugin-progress';
|
||||||
|
import { setupElegantRouter } from './router';
|
||||||
|
import { setupUnocss } from './unocss';
|
||||||
|
import { setupUnplugin } from './unplugin';
|
||||||
|
import { setupHtmlPlugin } from './html';
|
||||||
|
import { setupDevtoolsPlugin } from './devtools';
|
||||||
|
|
||||||
|
export function setupVitePlugins(viteEnv: Env.ImportMeta, buildTime: string) {
|
||||||
|
const plugins: PluginOption = [
|
||||||
|
vue(),
|
||||||
|
vueJsx(),
|
||||||
|
setupDevtoolsPlugin(viteEnv),
|
||||||
|
setupElegantRouter(),
|
||||||
|
setupUnocss(viteEnv),
|
||||||
|
...setupUnplugin(viteEnv),
|
||||||
|
progress(),
|
||||||
|
setupHtmlPlugin(buildTime)
|
||||||
|
];
|
||||||
|
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
41
build/plugins/router.ts
Normal file
41
build/plugins/router.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import type { RouteMeta } from 'vue-router';
|
||||||
|
import ElegantVueRouter from '@elegant-router/vue/vite';
|
||||||
|
import type { RouteKey } from '@elegant-router/types';
|
||||||
|
|
||||||
|
export function setupElegantRouter() {
|
||||||
|
return ElegantVueRouter({
|
||||||
|
layouts: {
|
||||||
|
base: 'src/layouts/base-layout/index.vue',
|
||||||
|
blank: 'src/layouts/blank-layout/index.vue'
|
||||||
|
},
|
||||||
|
routePathTransformer(routeName, routePath) {
|
||||||
|
const key = routeName as RouteKey;
|
||||||
|
|
||||||
|
if (key === 'login') {
|
||||||
|
const modules: UnionKey.LoginModule[] = ['pwd-login', 'code-login', 'register', 'reset-pwd', 'bind-wechat'];
|
||||||
|
|
||||||
|
const moduleReg = modules.join('|');
|
||||||
|
|
||||||
|
return `/login/:module(${moduleReg})?`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return routePath;
|
||||||
|
},
|
||||||
|
onRouteMetaGen(routeName) {
|
||||||
|
const key = routeName as RouteKey;
|
||||||
|
|
||||||
|
const constantRoutes: RouteKey[] = ['login', '403', '404', '500'];
|
||||||
|
|
||||||
|
const meta: Partial<RouteMeta> = {
|
||||||
|
title: key,
|
||||||
|
i18nKey: `route.${key}` as App.I18n.I18nKey
|
||||||
|
};
|
||||||
|
|
||||||
|
if (constantRoutes.includes(key)) {
|
||||||
|
meta.constant = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
32
build/plugins/unocss.ts
Normal file
32
build/plugins/unocss.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import process from 'node:process';
|
||||||
|
import path from 'node:path';
|
||||||
|
import unocss from '@unocss/vite';
|
||||||
|
import presetIcons from '@unocss/preset-icons';
|
||||||
|
import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders';
|
||||||
|
|
||||||
|
export function setupUnocss(viteEnv: Env.ImportMeta) {
|
||||||
|
const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv;
|
||||||
|
|
||||||
|
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon');
|
||||||
|
|
||||||
|
/** The name of the local icon collection */
|
||||||
|
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '');
|
||||||
|
|
||||||
|
return unocss({
|
||||||
|
presets: [
|
||||||
|
presetIcons({
|
||||||
|
prefix: `${VITE_ICON_PREFIX}-`,
|
||||||
|
scale: 1,
|
||||||
|
extraProperties: {
|
||||||
|
display: 'inline-block'
|
||||||
|
},
|
||||||
|
collections: {
|
||||||
|
[collectionName]: FileSystemIconLoader(localIconPath, svg =>
|
||||||
|
svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ')
|
||||||
|
)
|
||||||
|
},
|
||||||
|
warn: true
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
47
build/plugins/unplugin.ts
Normal file
47
build/plugins/unplugin.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import process from 'node:process';
|
||||||
|
import path from 'node:path';
|
||||||
|
import type { PluginOption } from 'vite';
|
||||||
|
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
|
||||||
|
import Icons from 'unplugin-icons/vite';
|
||||||
|
import IconsResolver from 'unplugin-icons/resolver';
|
||||||
|
import Components from 'unplugin-vue-components/vite';
|
||||||
|
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers';
|
||||||
|
import { FileSystemIconLoader } from 'unplugin-icons/loaders';
|
||||||
|
|
||||||
|
export function setupUnplugin(viteEnv: Env.ImportMeta) {
|
||||||
|
const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv;
|
||||||
|
|
||||||
|
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon');
|
||||||
|
|
||||||
|
/** The name of the local icon collection */
|
||||||
|
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '');
|
||||||
|
|
||||||
|
const plugins: PluginOption[] = [
|
||||||
|
Icons({
|
||||||
|
compiler: 'vue3',
|
||||||
|
customCollections: {
|
||||||
|
[collectionName]: FileSystemIconLoader(localIconPath, svg =>
|
||||||
|
svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ')
|
||||||
|
)
|
||||||
|
},
|
||||||
|
scale: 1,
|
||||||
|
defaultClass: 'inline-block'
|
||||||
|
}),
|
||||||
|
Components({
|
||||||
|
dts: 'src/typings/components.d.ts',
|
||||||
|
types: [{ from: 'vue-router', names: ['RouterLink', 'RouterView'] }],
|
||||||
|
resolvers: [
|
||||||
|
NaiveUiResolver(),
|
||||||
|
IconsResolver({ customCollections: [collectionName], componentPrefix: VITE_ICON_PREFIX })
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
createSvgIconsPlugin({
|
||||||
|
iconDirs: [localIconPath],
|
||||||
|
symbolId: `${VITE_ICON_LOCAL_PREFIX}-[dir]-[name]`,
|
||||||
|
inject: 'body-last',
|
||||||
|
customDomId: '__SVG_ICON_LOCAL__'
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
6
check_database.bat
Normal file
6
check_database.bat
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
@echo off
|
||||||
|
echo 检查数据库当前状态...
|
||||||
|
echo.
|
||||||
|
mysql -h localhost -P 3306 -u root -proot soybean_admin < check_database.sql
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
31
check_database.sql
Normal file
31
check_database.sql
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
-- 检查数据库当前状态
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
-- 查看所有路由的名称和组件路径
|
||||||
|
SELECT
|
||||||
|
route_id,
|
||||||
|
name AS '路由名称',
|
||||||
|
path AS '路径',
|
||||||
|
component AS '组件路径',
|
||||||
|
order_num AS '排序'
|
||||||
|
FROM sys_route
|
||||||
|
WHERE status = 1
|
||||||
|
ORDER BY order_num;
|
||||||
|
|
||||||
|
-- 特别检查可能重复的路由
|
||||||
|
SELECT
|
||||||
|
name,
|
||||||
|
COUNT(*) as '出现次数'
|
||||||
|
FROM sys_route
|
||||||
|
WHERE status = 1
|
||||||
|
GROUP BY name
|
||||||
|
HAVING COUNT(*) > 1;
|
||||||
|
|
||||||
|
-- 检查 user-manage 和 my-device 相关路由
|
||||||
|
SELECT
|
||||||
|
name AS '路由名称',
|
||||||
|
component AS '组件路径'
|
||||||
|
FROM sys_route
|
||||||
|
WHERE (name LIKE '%user%' OR name LIKE '%my_%')
|
||||||
|
AND status = 1
|
||||||
|
ORDER BY name;
|
||||||
14
check_role_menus.sql
Normal file
14
check_role_menus.sql
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
-- 检查角色配置的菜单
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
SELECT role_code, role_name, menus
|
||||||
|
FROM sys_role
|
||||||
|
WHERE role_code IN ('R_SUPER', 'R_ADMIN')
|
||||||
|
AND status = 1;
|
||||||
|
|
||||||
|
-- 检查数据库中实际的路由名称
|
||||||
|
SELECT name, path
|
||||||
|
FROM sys_route
|
||||||
|
WHERE name LIKE '%user%'
|
||||||
|
AND status = 1
|
||||||
|
ORDER BY name;
|
||||||
8
check_user_manage_routes.sql
Normal file
8
check_user_manage_routes.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
-- 检查用户管理相关路由
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
SELECT '=== 用户管理相关路由 ===' AS info;
|
||||||
|
SELECT route_id, name, path, component
|
||||||
|
FROM sys_route
|
||||||
|
WHERE route_id IN ('user_manage', 'user_list', 'user_role', 'user_permission')
|
||||||
|
ORDER BY order_num;
|
||||||
28
debug_user_manage.sql
Normal file
28
debug_user_manage.sql
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
-- 调试用户管理路由配置
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
SELECT '=== 用户管理所有路由 ===' AS info;
|
||||||
|
SELECT route_id, name, path, component, order_num, status
|
||||||
|
FROM sys_route
|
||||||
|
WHERE name LIKE '%user%' OR name LIKE '%manage%'
|
||||||
|
ORDER BY order_num;
|
||||||
|
|
||||||
|
SELECT '' AS '';
|
||||||
|
SELECT '=== R_SUPER 角色的菜单配置 ===' AS info;
|
||||||
|
SELECT role_code, menus
|
||||||
|
FROM sys_role
|
||||||
|
WHERE role_code = 'R_SUPER';
|
||||||
|
|
||||||
|
SELECT '' AS '';
|
||||||
|
SELECT '=== 检查子路由是否在角色配置中 ===' AS info;
|
||||||
|
SELECT
|
||||||
|
r.name AS route_name,
|
||||||
|
CASE
|
||||||
|
WHEN role.menus LIKE CONCAT('%', r.name, '%') THEN 'YES'
|
||||||
|
ELSE 'NO'
|
||||||
|
END AS in_role_config
|
||||||
|
FROM sys_route r
|
||||||
|
CROSS JOIN sys_role role
|
||||||
|
WHERE role.role_code = 'R_SUPER'
|
||||||
|
AND r.name LIKE '%user%'
|
||||||
|
ORDER BY r.order_num;
|
||||||
36
diagnose_user_manage.sql
Normal file
36
diagnose_user_manage.sql
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
-- 诊断用户管理菜单问题
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT '检查用户管理相关路由' AS '';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT route_id, name, path, component, status, order_num
|
||||||
|
FROM sys_route
|
||||||
|
WHERE route_id LIKE 'user%' OR name LIKE 'user%'
|
||||||
|
ORDER BY order_num;
|
||||||
|
|
||||||
|
SELECT '' AS '';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT '检查 R_SUPER 角色的菜单配置' AS '';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT role_code, role_name, menus
|
||||||
|
FROM sys_role
|
||||||
|
WHERE role_code = 'R_SUPER';
|
||||||
|
|
||||||
|
SELECT '' AS '';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT '检查子路由是否在角色配置中' AS '';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT
|
||||||
|
r.route_id,
|
||||||
|
r.name AS route_name,
|
||||||
|
r.path,
|
||||||
|
CASE
|
||||||
|
WHEN role.menus LIKE CONCAT('%', r.name, '%') THEN '✓ 在配置中'
|
||||||
|
ELSE '✗ 不在配置中 - 会被过滤!'
|
||||||
|
END AS in_role_config
|
||||||
|
FROM sys_route r
|
||||||
|
CROSS JOIN sys_role role
|
||||||
|
WHERE role.role_code = 'R_SUPER'
|
||||||
|
AND (r.route_id LIKE 'user%' OR r.name LIKE 'user%')
|
||||||
|
ORDER BY r.order_num;
|
||||||
24
eslint.config.js
Normal file
24
eslint.config.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { defineConfig } from '@soybeanjs/eslint-config';
|
||||||
|
|
||||||
|
export default defineConfig(
|
||||||
|
{ vue: true, unocss: true },
|
||||||
|
{
|
||||||
|
rules: {
|
||||||
|
'vue/multi-word-component-names': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
ignores: ['index', 'App', 'Register', '[id]', '[url]']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'vue/component-name-in-template-casing': [
|
||||||
|
'warn',
|
||||||
|
'PascalCase',
|
||||||
|
{
|
||||||
|
registeredComponentsOnly: false,
|
||||||
|
ignores: ['/^icon-/']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'unocss/order-attributify': 'off'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
24
fix_all_routes_final.bat
Normal file
24
fix_all_routes_final.bat
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo 最终完整修复所有路由配置
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 此脚本将修复:
|
||||||
|
echo 1. 路由名称(与前端 routeMap 保持一致)
|
||||||
|
echo 2. 组件路径(父路由用 layout.base,子路由用 view.xxx)
|
||||||
|
echo 3. 角色菜单配置(使用正确的路由名称)
|
||||||
|
echo.
|
||||||
|
|
||||||
|
mysql -u root -proot < fix_all_routes_final.sql
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 修复完成!
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 下一步操作:
|
||||||
|
echo 1. 重启后端服务(运行 backend\start.bat)
|
||||||
|
echo 2. 清除浏览器缓存(Ctrl+Shift+Delete)
|
||||||
|
echo 3. 刷新浏览器页面(Ctrl+F5)
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
127
fix_all_routes_final.sql
Normal file
127
fix_all_routes_final.sql
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
-- 最终完整修复所有路由配置
|
||||||
|
-- 此脚本将路由名称与前端 routeMap 保持一致
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 第一部分:修复所有路由的 name 字段
|
||||||
|
-- 规则:与前端 src/router/elegant/transform.ts 中的 routeMap 保持一致
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- 设备管理
|
||||||
|
UPDATE sys_route SET name = 'device' WHERE route_id = 'device';
|
||||||
|
UPDATE sys_route SET name = 'device_list' WHERE route_id = 'device_list';
|
||||||
|
UPDATE sys_route SET name = 'device_online' WHERE route_id = 'device_online';
|
||||||
|
UPDATE sys_route SET name = 'device_power' WHERE route_id = 'device_power';
|
||||||
|
UPDATE sys_route SET name = 'device_monitor' WHERE route_id = 'device_monitor';
|
||||||
|
UPDATE sys_route SET name = 'device_group' WHERE route_id = 'device_group';
|
||||||
|
|
||||||
|
-- 屏幕监控
|
||||||
|
UPDATE sys_route SET name = 'screen' WHERE route_id = 'screen';
|
||||||
|
UPDATE sys_route SET name = 'screen_wall' WHERE route_id = 'screen_wall';
|
||||||
|
UPDATE sys_route SET name = 'screen_control' WHERE route_id = 'screen_control';
|
||||||
|
UPDATE sys_route SET name = 'screen_record' WHERE route_id = 'screen_record';
|
||||||
|
|
||||||
|
-- 用户管理(父路由用连字符,子路由用连字符+下划线)
|
||||||
|
UPDATE sys_route SET name = 'user-manage' WHERE route_id = 'user_manage';
|
||||||
|
UPDATE sys_route SET name = 'user-manage_list' WHERE route_id = 'user_list';
|
||||||
|
UPDATE sys_route SET name = 'user-manage_role' WHERE route_id = 'user_role';
|
||||||
|
UPDATE sys_route SET name = 'user-manage_permission' WHERE route_id = 'user_permission';
|
||||||
|
|
||||||
|
-- 申请管理
|
||||||
|
UPDATE sys_route SET name = 'application' WHERE route_id = 'application';
|
||||||
|
UPDATE sys_route SET name = 'application_approval' WHERE route_id = 'application_approval';
|
||||||
|
UPDATE sys_route SET name = 'application_history' WHERE route_id = 'application_history';
|
||||||
|
|
||||||
|
-- 系统设置
|
||||||
|
UPDATE sys_route SET name = 'system' WHERE route_id = 'system';
|
||||||
|
UPDATE sys_route SET name = 'system_amt' WHERE route_id = 'system_amt';
|
||||||
|
UPDATE sys_route SET name = 'system_agent' WHERE route_id = 'system_agent';
|
||||||
|
UPDATE sys_route SET name = 'system_log' WHERE route_id = 'system_log';
|
||||||
|
|
||||||
|
-- 我的设备(父路由用连字符,子路由用连字符+下划线)
|
||||||
|
UPDATE sys_route SET name = 'my-device' WHERE route_id = 'my_device';
|
||||||
|
UPDATE sys_route SET name = 'my-device_status' WHERE route_id = 'my_device_status';
|
||||||
|
UPDATE sys_route SET name = 'my-device_power-control' WHERE route_id = 'my_device_power';
|
||||||
|
UPDATE sys_route SET name = 'my-device_remote-control' WHERE route_id = 'my_device_remote';
|
||||||
|
|
||||||
|
-- 设备申请(父路由用连字符,子路由用连字符+下划线)
|
||||||
|
UPDATE sys_route SET name = 'my-application' WHERE route_id = 'my_application';
|
||||||
|
UPDATE sys_route SET name = 'my-application_apply' WHERE route_id = 'my_application_apply';
|
||||||
|
UPDATE sys_route SET name = 'my-application_my-list' WHERE route_id = 'my_application_list';
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 第二部分:修复组件路径
|
||||||
|
-- 规则:父路由只用 layout.base,子路由用 view.{folder}_{subfolder}
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- 设备管理
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'device';
|
||||||
|
UPDATE sys_route SET component = 'view.device_list' WHERE route_id = 'device_list';
|
||||||
|
UPDATE sys_route SET component = 'view.device_online' WHERE route_id = 'device_online';
|
||||||
|
UPDATE sys_route SET component = 'view.device_power' WHERE route_id = 'device_power';
|
||||||
|
UPDATE sys_route SET component = 'view.device_monitor' WHERE route_id = 'device_monitor';
|
||||||
|
UPDATE sys_route SET component = 'view.device_group' WHERE route_id = 'device_group';
|
||||||
|
|
||||||
|
-- 屏幕监控
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'screen';
|
||||||
|
UPDATE sys_route SET component = 'view.screen_wall' WHERE route_id = 'screen_wall';
|
||||||
|
UPDATE sys_route SET component = 'view.screen_control' WHERE route_id = 'screen_control';
|
||||||
|
UPDATE sys_route SET component = 'view.screen_record' WHERE route_id = 'screen_record';
|
||||||
|
|
||||||
|
-- 用户管理
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'user_manage';
|
||||||
|
UPDATE sys_route SET component = 'view.user-manage_list' WHERE route_id = 'user_list';
|
||||||
|
UPDATE sys_route SET component = 'view.user-manage_role' WHERE route_id = 'user_role';
|
||||||
|
UPDATE sys_route SET component = 'view.user-manage_permission' WHERE route_id = 'user_permission';
|
||||||
|
|
||||||
|
-- 申请管理
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'application';
|
||||||
|
UPDATE sys_route SET component = 'view.application_approval' WHERE route_id = 'application_approval';
|
||||||
|
UPDATE sys_route SET component = 'view.application_history' WHERE route_id = 'application_history';
|
||||||
|
|
||||||
|
-- 系统设置
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'system';
|
||||||
|
UPDATE sys_route SET component = 'view.system_amt' WHERE route_id = 'system_amt';
|
||||||
|
UPDATE sys_route SET component = 'view.system_agent' WHERE route_id = 'system_agent';
|
||||||
|
UPDATE sys_route SET component = 'view.system_log' WHERE route_id = 'system_log';
|
||||||
|
|
||||||
|
-- 我的设备
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'my_device';
|
||||||
|
UPDATE sys_route SET component = 'view.my-device_status' WHERE route_id = 'my_device_status';
|
||||||
|
UPDATE sys_route SET component = 'view.my-device_power-control' WHERE route_id = 'my_device_power';
|
||||||
|
UPDATE sys_route SET component = 'view.my-device_remote-control' WHERE route_id = 'my_device_remote';
|
||||||
|
|
||||||
|
-- 设备申请
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'my_application';
|
||||||
|
UPDATE sys_route SET component = 'view.my-application_apply' WHERE route_id = 'my_application_apply';
|
||||||
|
UPDATE sys_route SET component = 'view.my-application_my-list' WHERE route_id = 'my_application_list';
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 第三部分:更新角色的菜单配置
|
||||||
|
-- 规则:使用与路由 name 字段完全一致的名称
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
UPDATE sys_role
|
||||||
|
SET menus = 'device,device_list,device_group,device_monitor,device_online,device_power,screen,screen_wall,screen_control,screen_record,user-manage,user-manage_list,user-manage_role,user-manage_permission,application,application_approval,application_history,system,system_agent,system_amt,system_log,my-device,my-device_status,my-device_remote-control,my-device_power-control,my-application,my-application_apply,my-application_my-list'
|
||||||
|
WHERE role_code = 'R_SUPER';
|
||||||
|
|
||||||
|
UPDATE sys_role
|
||||||
|
SET menus = 'device,device_list,device_group,device_monitor,device_online,device_power,screen,screen_wall,screen_control,screen_record,user-manage,user-manage_list,user-manage_role,application,application_approval,application_history'
|
||||||
|
WHERE role_code = 'R_ADMIN';
|
||||||
|
|
||||||
|
UPDATE sys_role
|
||||||
|
SET menus = 'my-device,my-device_status,my-device_remote-control,my-device_power-control,my-application,my-application_apply,my-application_my-list'
|
||||||
|
WHERE role_code = 'R_USER';
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 第四部分:验证修改结果
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
SELECT '=== 所有路由名称和组件路径 ===' AS info;
|
||||||
|
SELECT route_id, name, path, component, order_num
|
||||||
|
FROM sys_route
|
||||||
|
WHERE status = 1
|
||||||
|
ORDER BY order_num;
|
||||||
|
|
||||||
|
SELECT '=== 角色菜单配置 ===' AS info;
|
||||||
|
SELECT role_code, role_name, menus FROM sys_role;
|
||||||
40
fix_database.bat
Normal file
40
fix_database.bat
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo 修复数据库组件路径
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 此脚本将执行 SQL 修复,解决菜单显示问题
|
||||||
|
echo.
|
||||||
|
echo 请确保:
|
||||||
|
echo 1. MySQL 服务正在运行
|
||||||
|
echo 2. 数据库连接信息正确(localhost:3306, root/root)
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
|
||||||
|
mysql -h localhost -P 3306 -u root -proot soybean_admin < EXECUTE_THIS_FIX.sql
|
||||||
|
|
||||||
|
if %errorlevel% equ 0 (
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 修复成功!
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 接下来请:
|
||||||
|
echo 1. 重启后端服务(backend/start.bat)
|
||||||
|
echo 2. 刷新浏览器(Ctrl+Shift+R 强制刷新)
|
||||||
|
echo 3. 重新登录测试
|
||||||
|
echo.
|
||||||
|
) else (
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 修复失败!
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 请检查:
|
||||||
|
echo 1. MySQL 是否正在运行
|
||||||
|
echo 2. 数据库连接信息是否正确
|
||||||
|
echo 3. 是否有足够的权限
|
||||||
|
echo.
|
||||||
|
)
|
||||||
|
|
||||||
|
pause
|
||||||
18
fix_parent_routes_component.bat
Normal file
18
fix_parent_routes_component.bat
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo 修复父路由组件路径
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 将所有父路由的 component 改为 layout.base
|
||||||
|
echo.
|
||||||
|
|
||||||
|
mysql -u root -proot < fix_parent_routes_component.sql
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 修复完成!
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 下一步:重启后端服务并刷新浏览器
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
18
fix_parent_routes_component.sql
Normal file
18
fix_parent_routes_component.sql
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
-- 修复父路由的组件路径
|
||||||
|
-- 父路由(有子菜单的)应该只用 layout.base,不需要指定具体视图
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
-- 修复所有父路由的 component 字段
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'device';
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'screen';
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'user_manage';
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'application';
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'system';
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'my_device';
|
||||||
|
UPDATE sys_route SET component = 'layout.base' WHERE route_id = 'my_application';
|
||||||
|
|
||||||
|
-- 验证修改结果
|
||||||
|
SELECT '=== 父路由组件路径(应该都是 layout.base)===' AS info;
|
||||||
|
SELECT route_id, name, component
|
||||||
|
FROM sys_route
|
||||||
|
WHERE route_id IN ('device', 'screen', 'user_manage', 'application', 'system', 'my_device', 'my_application');
|
||||||
28
fix_route_id_name.bat
Normal file
28
fix_route_id_name.bat
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo 修复路由 ID 和名称不一致问题
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 这将修复数据库中 route_id 和 name 字段的不一致
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
|
||||||
|
mysql -h localhost -P 3306 -u root -proot soybean_admin < fix_route_id_name.sql
|
||||||
|
|
||||||
|
if %errorlevel% equ 0 (
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 修复成功!
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 请重启后端服务并刷新浏览器测试
|
||||||
|
echo.
|
||||||
|
) else (
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 修复失败!
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
)
|
||||||
|
|
||||||
|
pause
|
||||||
19
fix_route_id_name.sql
Normal file
19
fix_route_id_name.sql
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-- 修复数据库中 route_id 和 name 字段的混乱
|
||||||
|
-- 问题:route_id 和 name 字段值不一致,导致路由层级判断错误
|
||||||
|
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
-- 查看当前问题数据
|
||||||
|
SELECT route_id AS '错误的route_id', name AS '正确的name', path
|
||||||
|
FROM sys_route
|
||||||
|
WHERE route_id != name
|
||||||
|
ORDER BY order_num;
|
||||||
|
|
||||||
|
-- 修复:将 route_id 设置为与 name 一致
|
||||||
|
UPDATE sys_route SET route_id = name WHERE route_id != name;
|
||||||
|
|
||||||
|
-- 验证修复结果
|
||||||
|
SELECT route_id, name, path, component
|
||||||
|
FROM sys_route
|
||||||
|
WHERE status = 1
|
||||||
|
ORDER BY order_num;
|
||||||
16
fix_user_manage_children.bat
Normal file
16
fix_user_manage_children.bat
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo 修复用户管理子路由组件路径
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
mysql -u root -proot < fix_user_manage_children.sql
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 修复完成!
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 下一步:重启后端服务并刷新浏览器
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
14
fix_user_manage_children.sql
Normal file
14
fix_user_manage_children.sql
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
-- 修复用户管理子路由的组件路径
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
-- 修复用户管理的三个子路由
|
||||||
|
UPDATE sys_route SET component = 'view.user-manage_list' WHERE route_id = 'user_list';
|
||||||
|
UPDATE sys_route SET component = 'view.user-manage_role' WHERE route_id = 'user_role';
|
||||||
|
UPDATE sys_route SET component = 'view.user-manage_permission' WHERE route_id = 'user_permission';
|
||||||
|
|
||||||
|
-- 验证修改结果
|
||||||
|
SELECT '=== 用户管理路由配置 ===' AS info;
|
||||||
|
SELECT route_id, name, path, component
|
||||||
|
FROM sys_route
|
||||||
|
WHERE route_id IN ('user_manage', 'user_list', 'user_role', 'user_permission')
|
||||||
|
ORDER BY order_num;
|
||||||
6
fix_user_manage_final.bat
Normal file
6
fix_user_manage_final.bat
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
@echo off
|
||||||
|
echo 修复用户管理菜单问题...
|
||||||
|
mysql -u root -proot < fix_user_manage_final.sql
|
||||||
|
echo.
|
||||||
|
echo 修复完成!请重启后端服务并刷新浏览器。
|
||||||
|
pause
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user