23 Commits

Author SHA1 Message Date
ae3a01fb7b revert: 回退全局响应结果处理器(遗漏项) 2024-01-26 22:21:10 +08:00
5ee430cbfa docs: 完善 README 文档 2023-12-03 00:13:44 +08:00
1fc76a4123 refactor: 优化部分注解使用 2023-11-30 22:14:19 +08:00
2146605a86 revert: 回退全局响应结果处理器
1.影响 API 文档生成
2.其他已知及未知影响
2023-11-30 22:09:44 +08:00
cde515b186 !8 回退全局响应结果处理器
Merge pull request !8 from Yoofff/1.3.x
2023-11-30 14:05:50 +00:00
Bull-BCLS
d668620bfe refactor: 回退全局响应结果处理器
1.影响 API 文档生成
2.其他已知及未知影响
2023-11-29 23:34:00 +08:00
27d401f44b docs: 完善 README 文档 2023-11-20 20:12:06 +08:00
a8aa9f28f6 chore: 移除 XML 文件头部的协议信息 2023-11-19 18:15:48 +08:00
2930619964 chore: 新增 idea 图标 2023-11-19 18:13:37 +08:00
11b3b87337 fix: 修复保存生成配置校验失效的问题,并优化部分提示效果 2023-11-16 21:18:01 +08:00
0eddbfb978 refactor: 优化菜单标题校验 2023-11-16 21:13:10 +08:00
adf6d900f3 chore: 更新版本号 2023-11-16 21:12:59 +08:00
3f8f4e2bf4 release: v1.3.1 2023-11-15 21:12:04 +08:00
3fcdb54442 fix: sms4j 3.0.3 => 3.0.4
修复发送容联云短信错误
2023-11-15 20:57:04 +08:00
5d159c6ab3 fix: 发送消息增加事务处理 2023-11-15 20:55:27 +08:00
39969ebf61 chore: 完善 Redis 部署配置 2023-11-12 00:21:04 +08:00
47a5746794 fix: 修复仪表盘访问趋势区块 y 轴数值过大时无法展示的问题
增加 y 轴单位转换逻辑
2023-11-11 00:09:18 +08:00
8820c1dfc8 refactor: 优化 401 状态处理逻辑
1.退出接口增加登录校验
2.前端获取用户信息失败,自动清理客户端信息并跳转回登录页
2023-11-07 19:53:29 +08:00
712eedba1b refactor: 优化超时登录处理逻辑 2023-11-06 22:12:27 +08:00
47a8160d70 fix: 修复控制台报错 Please use theme before using plugins
1.由 v-md-editor 使用方式不佳引起
2023-11-05 23:23:54 +08:00
b63d7d725d fix: 修复 Swagger 分组接口缺失 2023-11-05 21:11:34 +08:00
f15494d348 style: 优化部分变量命名 2023-11-05 17:36:41 +08:00
91ea4ed685 chore: 更新版本号 2023-11-05 17:30:23 +08:00
1246 changed files with 54235 additions and 30520 deletions

View File

@@ -0,0 +1,46 @@
<!--
感谢您使用 ContiNew Admin请您花些时间填写这份 Issue 调查,非常感谢您的反馈!
-->
<!-- 在 [] 中输入 x 来勾选) -->
## Issue 类型
- [ ] 缺陷报告Bug
- [ ] 需求建议Feature
## Issue 描述
<!-- 清楚而简洁地描述您遇到的问题。例如:在使用 xxx 功能时发现 xxx 问题。另外,非常欢迎您对此 Issue 提交 PR。 -->
## 复现步骤(如果是提交 Feature Issue请删除本项
<!-- 条理清晰的步骤或演示视频可以帮助快速定位问题。例如1、xxx; 2、xxx; -->
## 预期结果(如果是提交 Feature Issue请删除本项
<!-- 清楚而简洁地描述您期望的结果。 -->
## 环境信息(如果是提交 Feature Issue请删除本项
<!-- 描述清楚您所使用的相关环境例如JDK 版本1.8.0_202框架版本v1.0.0;其他可能与该 issue 相关的依赖版本。 -->
## 解决方案(如果是提交 Bug Issue请删除本项
<!-- 清楚而简洁地描述您想要的解决方案。 -->
## 替代方案(如果是提交 Bug Issue请删除本项
<!-- 清楚而简洁地描述您考虑过的任何替代解决方案或功能。 -->
## 额外补充
<!-- Bug添加您的完整报错信息或屏幕截图以及一切能帮助定位问题的信息。 -->
<!-- Feature添加您在其他框架或场景遇见的效果截图或链接以及一切能帮助理解 Feature 的信息。 -->
## 提交前确认
<!-- 在提交 issue 之前,请确保执行过以下操作。 -->
- [ ] 阅读[文档](https://doc.charles7c.top/faq.html)
- [ ] 搜索是否有其他人提交过类似的 issue如果对应 issue 尚未解决,您可以先订阅关注该 issue为了方便后来者查找问题解决方法请尽量避免创建重复的 issue

View File

@@ -0,0 +1,53 @@
<!--
非常感谢您的 PR在提交之前请务必确保您 PR 的代码经过了完整测试,并且通过了代码规范检查。
-->
<!-- 在 [] 中输入 x 来勾选) -->
## PR 类型
<!-- 您的 PR 引入了哪种类型的变更? -->
<!-- 只支持选择一种类型,如果有多种类型,可以在更新日志中增加 “类型” 列。 -->
- [ ] 新 feature
- [ ] Bug 修复
- [ ] 功能增强
- [ ] 文档变更
- [ ] 代码样式变更
- [ ] 重构
- [ ] 性能改进
- [ ] 单元测试
- [ ] CI/CD
- [ ] 其他
## PR 目的
<!-- 描述一下您的 PR 解决了什么问题。如果可以,请链接到相关 issues。 -->
## 解决方案
<!-- 详细描述您是如何解决的问题 -->
## PR 测试
<!-- 如果可以,请为您的 PR 添加或更新单元测试。 -->
<!-- 请描述一下您是如何测试 PR 的。例如:创建/更新单元测试或添加相关的截图。 -->
## Changelog
| 模块 | Changelog | Related issues |
|-----|-----------| -------------- |
| | | |
<!-- 如果有多种类型的变更,可以在变更日志表中增加 “类型” 列,该列的值与上方 “PR 类型” 相同。 -->
<!-- Related issues 格式为 fixes #<issue号>,或者 resolves #<issue号>。 -->
## 其他信息
<!-- 请描述一下还有哪些注意事项。例如:如果引入了一个不向下兼容的变更,请描述其影响。 -->
## 提交前确认
- [ ] PR 代码经过了完整测试,并且通过了代码规范检查
- [ ] 已经完整填写 Changelog并链接到了相关 issues
- [ ] PR 代码将要提交到 dev 分支

View File

@@ -1,38 +1,11 @@
name: "\U0001F41E Bug 报告"
description: 在使用 xxx 功能时出现异常
title: "[Bug] "
labels: ["bug"]
description: Create a report to help us improve
labels: ['bug: pending triage']
body:
- type: markdown
attributes:
value: |
感谢您使用 ContiNew Admin请您花些时间填写这份 Bug 报告。
- type: checkboxes
id: checkboxes
attributes:
label: 请您确认
description: 在提交 Bug 之前,请确认执行过以下操作。
options:
- label: 重启项目和 IDE 后,仍然能够复现此问题
required: true
- label: 查阅过 [使用指南](https://continew.top/admin/backend/structure.html) 和 [常见问题](https://continew.top/admin/faq.html) ,仍无解决方法
required: true
- label: 查看过控制台是否有报错,如果有报错,下拉控制台到最下查找过 Caused 提示(如果有 Caused 关键字,一般其后都有直观提示,请自行翻译英文),并百度或 Google 后,仍无法解决
required: true
- label: 尝试了最新 dev 分支代码(演示环境),仍有相同问题
required: true
- label: 搜索了项目 Issues没有其他人提交过类似的 Bug如果对应 Bug 尚未解决,您可以先订阅关注该 Issue为了方便后来者查找问题解决方法请避免创建重复的 Issue
required: true
- label: 【后端】确认不是依赖组件相关的问题例如sa-token、mybatis-plus、snail-job、crane4j、cosid等如有此类组件相关的问题请提交至对应组件仓库
required: true
- label: 【前端】确认不是 gi-demo 前端模板相关的组件问题例如GiTable、GiForm、基础布局和配置等如有此类组件相关的问题请提交至 [gi-demo](https://gitee.com/lin0716/gi-demo) 或对应组件仓库)
required: true
- label: 阅读了源码并在 IDE 中进行断点调试
required: false
- label: 是否愿意为您提出的 Bug 提交 PR
required: false
validations:
required: true
- type: textarea
id: bug-description
attributes:
@@ -45,7 +18,7 @@ body:
id: reproduction
attributes:
label: 复现步骤
description: 条理清晰的步骤及图片或演示视频可以帮助快速定位问题。
description: 条理清晰的步骤或演示视频可以帮助快速定位问题。
placeholder: 例如1、xxx; 2、xxx;
validations:
required: true
@@ -60,12 +33,9 @@ body:
- type: textarea
id: environment-info
attributes:
label: 版本信息
description: 请务必填写版本信息(项目启动后在控制台可以查看到),否则视为无效问题
value: |
NPM 版本:
PNPM 版本:
ContiNew Admin 版本:
label: 环境信息
description: 描述清楚您所使用的相关环境例如JDK 版本1.8.0_202框架版本v1.0.0;其他可能与该 issue 相关的依赖版本
placeholder: JDK 版本, 框架版本等
validations:
required: true
- type: textarea
@@ -73,3 +43,15 @@ body:
attributes:
label: 额外补充
description: 添加您的完整报错信息或屏幕截图,以及一切能帮助定位问题的信息。
- type: checkboxes
id: checkboxes
attributes:
label: 确认
description: 在提交 issue 之前,请确保执行过以下操作。
options:
- label: 阅读[文档](https://doc.charles7c.top/faq.html)
required: true
- label: 根据报错信息百度或 Google 一下
required: true
- label: 搜索是否有其他人提交过类似的 issue如果对应 issue 尚未解决,您可以先订阅关注该 issue为了方便后来者查找问题解决方法请尽量避免创建重复的 issue
required: true

View File

@@ -1,34 +1,10 @@
name: "\U0001F680 新 Feature 建议"
description: 我希望增加 xxx 功能;现有的 xxx 功能不好用...
title: "[Feature] "
labels: ["feature"]
description: Suggest an idea for this project
body:
- type: markdown
attributes:
value: |
感谢您使用 ContiNew Admin请您花些时间填写这份 Feature 调查。
- type: checkboxes
id: checkboxes
attributes:
label: 请您确认
description: 在提交 Feature 之前,请确认执行过以下操作。
options:
- label: 尝试了最新 dev 分支代码(演示环境),仍没有该功能
required: true
- label: 查阅过 [使用指南](https://continew.top/admin/backend/structure.html) 和 [常见问题](https://continew.top/admin/faq.html) ,仍然认为很有必要
required: true
- label: 查阅过 [需求墙](https://continew.top/admin/other/feature.html),仍没有该功能计划
required: true
- label: 搜索了项目 Issues没有其他人提交过类似的 Feature如果对应 Feature 尚未实现,您可以先订阅关注该 Issue为了方便后来者查找问题解决方法请避免创建重复的 Issue
required: true
- label: 【后端】确认不是依赖组件相关的需求例如sa-token、mybatis-plus、snail-job、crane4j、cosid等如有此类组件相关的需求请提交至对应组件仓库
required: true
- label: 【前端】确认不是基础组件类需求例如GiTable、GiForm、基础布局、纯前端组件锁屏、引导如有此类组件相关的需求请提交至 [gi-demo](https://gitee.com/lin0716/gi-demo) 或对应组件仓库)
required: true
- label: 是否愿意为您提出的 Feature 提交 PR
required: false
validations:
required: true
- type: textarea
id: feature-description
attributes:
@@ -54,3 +30,13 @@ body:
attributes:
label: 额外补充
description: 添加您在其他框架或场景遇见的效果截图或链接,以及一切能帮助理解 Feature 的信息。
- type: checkboxes
id: checkboxes
attributes:
label: 确认
description: 在提交 issue 之前,请确保执行过以下操作。
options:
- label: 阅读[文档](https://doc.charles7c.top/faq.html)
required: true
- label: 搜索是否有其他人提交过类似的 issue如果对应 issue 尚未解决,您可以先订阅关注该 issue为了方便后来者查找问题解决方法请尽量避免创建重复的 issue
required: true

View File

@@ -1,28 +0,0 @@
name: Build
on:
pull_request:
branches:
- dev
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
jdk-version:
- 17
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: "adopt"
java-version: ${{ matrix.jdk-version }}
cache: "maven"
- name: Compile
run: |
sed -i.bak '/<repositories>/,/<\/repositories>/d' pom.xml
sed -i.bak '/<pluginRepositories>/,/<\/pluginRepositories>/d' pom.xml
mvn -B compile --file pom.xml

View File

@@ -8,37 +8,34 @@ on:
workflow_dispatch:
jobs:
# 部署后端服务
deploy-server:
runs-on: ubuntu-latest
steps:
# 1、检出源码
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@master
# 2、安装 Java 环境
- name: Setup Java
uses: actions/setup-java@v4
uses: actions/setup-java@master
with:
distribution: "adopt"
java-version: 17
cache: "maven"
distribution: 'adopt'
java-version: '8'
cache: 'maven'
# 3、打包
- name: Build
run: |
sed -i.bak '/<repositories>/,/<\/repositories>/d' pom.xml
sed -i.bak '/<pluginRepositories>/,/<\/pluginRepositories>/d' pom.xml
mvn -B package --file pom.xml
run: mvn -B package --file pom.xml
# 4、拷贝到服务器
- name: Copy
uses: appleboy/scp-action@v0.1.7
uses: garygrossgarten/github-action-scp@release
with:
host: ${{ secrets.SERVER_HOST }}
port: ${{ secrets.SERVER_PORT }}
username: ${{ secrets.SERVER_USERNAME }}
password: ${{ secrets.SERVER_PASSWORD }}
source: ./continew-webapi/target/app/*
target: /docker/continew-admin
strip_components: 3
# 5、启动
local: ./continew-admin-webapi/target/app
remote: /docker/continew-admin
# 5、启动后端服务
- name: Start
uses: appleboy/ssh-action@master
with:
@@ -49,4 +46,54 @@ jobs:
script: |
cd /docker
docker-compose up --force-recreate --build -d continew-admin-server
docker images | grep none | awk '{print $3}' | xargs docker rmi
docker images | grep none | awk '{print $3}' | xargs docker rmi
# 部署前端
deploy-web:
runs-on: ubuntu-latest
steps:
# 1、检出源码
- name: Checkout
uses: actions/checkout@master
# 2、安装 PNPM
- name: Setup PNPM
uses: pnpm/action-setup@v2
with:
version: latest
# 3、安装 Node 环境
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 16
cache: pnpm
cache-dependency-path: ./continew-admin-ui/pnpm-lock.yaml
# 4、安装依赖
- name: Install Dependencies
run: pnpm i --frozen-lockfile
working-directory: ./continew-admin-ui
# 5、打包
- name: Build
run: pnpm build
working-directory: ./continew-admin-ui
# 6、拷贝到服务器
- name: Copy
uses: garygrossgarten/github-action-scp@release
with:
host: ${{ secrets.SERVER_HOST }}
port: ${{ secrets.SERVER_PORT }}
username: ${{ secrets.SERVER_USERNAME }}
password: ${{ secrets.SERVER_PASSWORD }}
local: ./continew-admin-ui/dist
remote: /docker/continew-admin/tmp
# 7、重启前端服务
- name: Restart
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
port: ${{ secrets.SERVER_PORT }}
username: ${{ secrets.SERVER_USERNAME }}
password: ${{ secrets.SERVER_PASSWORD }}
script: |
rm -rf /docker/continew-admin/web/*
mv /docker/continew-admin/tmp/* /docker/continew-admin/web
docker restart nginx

View File

@@ -3,11 +3,11 @@ name: Release
on:
push:
tags:
- "v*" # Push events to matching v*, i.e. v1.0.0
- 'v*' # Push events to matching v*, i.e. v1.0.0
jobs:
release:
if: github.repository == 'continew-org/continew-admin'
if: github.repository == 'Charles7c/continew-admin'
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -20,4 +20,4 @@ jobs:
with:
tag_name: ${{ github.ref }}
body: |
详情请参阅 [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/dev/CHANGELOG.md) 。
详情请参阅 [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/dev/CHANGELOG.md) 。

View File

@@ -1,48 +0,0 @@
name: Scan
on:
push:
branches:
- dev
pull_request:
branches:
- dev
jobs:
sonar-scan:
runs-on: ubuntu-latest
strategy:
matrix:
jdk-version:
- 17
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: "adopt"
java-version: ${{ matrix.jdk-version }}
cache: "maven"
- name: Cache SonarCloud packages
uses: actions/cache@v3
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Analyze
run: |
sed -i.bak '/<repositories>/,/<\/repositories>/d' pom.xml
sed -i.bak '/<pluginRepositories>/,/<\/pluginRepositories>/d' pom.xml
mvn -B verify -Psonar
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

4
.gitignore vendored
View File

@@ -33,12 +33,8 @@ build/
### VS Code ###
.vscode/
# Maven ignore
.flattened-pom.xml
### Temp ###
*.log
*.log.gz
*.logs
*.cache
*.diff

BIN
.idea/icon.png generated Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 KiB

After

Width:  |  Height:  |  Size: 678 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 KiB

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

File diff suppressed because it is too large Load Diff

728
README.md
View File

@@ -1,261 +1,157 @@
# ContiNew Admin 中后台管理框架
<a href="https://github.com/continew-org/continew-admin" title="Release" target="_blank">
<img src="https://img.shields.io/badge/RELEASE-v3.7.0-%23ff3f59.svg" alt="Release" />
</a>
<a href="https://github.com/continew-org/continew-starter" title="ContiNew Starter" target="_blank">
<img src="https://img.shields.io/badge/ContiNew Starter-2.12.2-%236CB52D.svg" alt="ContiNew Starter" />
</a>
<a href="https://spring.io/projects/spring-boot" title="Spring Boot" target="_blank">
<img src="https://img.shields.io/badge/Spring Boot-3.3.11-%236CB52D.svg?logo=Spring-Boot" alt="Spring Boot" />
</a>
<a href="https://github.com/continew-org/continew-admin" title="Open JDK" target="_blank">
<img src="https://img.shields.io/badge/Open JDK-17-%236CB52D.svg?logo=OpenJDK&logoColor=FFF" alt="Open JDK" />
</a>
<a href="https://app.codacy.com/gh/continew-org/continew-admin/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade" title="Codacy" target="_blank">
<img src="https://app.codacy.com/project/badge/Grade/19e3e2395d554efe902c3822e65db30e" alt="Codacy" />
</a>
<a href="https://sonarcloud.io/summary/new_code?id=Charles7c_continew-admin" title="Sonar" target="_blank">
<img src="https://sonarcloud.io/api/project_badges/measure?project=Charles7c_continew-admin&metric=alert_status" alt="Sonar" />
</a>
<br />
<a href="https://github.com/continew-org/continew-admin/blob/dev/LICENSE" title="License" target="_blank">
<a href="https://github.com/Charles7c/continew-admin/blob/dev/LICENSE" target="_blank">
<img src="https://img.shields.io/badge/License-Apache--2.0-blue.svg" alt="License" />
</a>
<a href="https://github.com/continew-org/continew-admin" title="GitHub Stars" target="_blank">
<img src="https://img.shields.io/github/stars/continew-org/continew-admin?style=social" alt="GitHub Stars" />
<a href="https://github.com/Charles7c/continew-admin" target="_blank">
<img src="https://img.shields.io/badge/SNAPSHOT-v1.3.2-%23ff3f59.svg" alt="Release" />
</a>
<a href="https://github.com/continew-org/continew-admin" title="GitHub Forks" target="_blank">
<img src="https://img.shields.io/github/forks/continew-org/continew-admin?style=social" alt="GitHub Forks" />
<a href="https://github.com/Charles7c/continew-admin" target="_blank">
<img src="https://img.shields.io/github/stars/Charles7c/continew-admin?style=social" alt="GitHub stars" />
</a>
<a href="https://gitee.com/continew/continew-admin" title="Gitee Stars" target="_blank">
<img src="https://gitee.com/continew/continew-admin/badge/star.svg?theme=dark" alt="Gitee Stars" />
<a href="https://github.com/Charles7c/continew-admin" target="_blank">
<img src="https://img.shields.io/github/forks/Charles7c/continew-admin?style=social" alt="GitHub forks" />
</a>
<a href="https://gitee.com/continew/continew-admin" title="Gitee Forks" target="_blank">
<img src="https://gitee.com/continew/continew-admin/badge/fork.svg?theme=dark" alt="Gitee Forks" />
<a href="https://gitee.com/Charles7c/continew-admin" target="_blank">
<img src="https://gitee.com/Charles7c/continew-admin/badge/star.svg?theme=white" alt="Gitee stars" />
</a>
<a href="https://gitcode.com/continew/continew-admin" title="GitCode Stars" target="_blank">
<img src="https://gitcode.com/continew/continew-admin/star/badge.svg" alt="GitCode Stars" />
<a href="https://gitee.com/Charles7c/continew-admin" target="_blank">
<img src="https://gitee.com/Charles7c/continew-admin/badge/fork.svg?theme=white" alt="Gitee forks" />
</a>
<img src="https://img.shields.io/badge/Spring Boot-2.7.16-%236CB52D.svg" alt="Release" />
<img src="https://img.shields.io/badge/Java-8-%236CB52D.svg" alt="Release" />
📚 [在线文档](https://continew.top) | 🚀 [演示地址](https://continew.top/admin/guide/demo.html)
📚 [在线文档](https://doc.charles7c.top) | ✨ [提交需求](https://doc.charles7c.top/require.html) | 🚀 [演示地址](https://cnadmin.charles7c.top)(账号/密码admin/admin123
## 简介
ContiNew AdminContinue New Admin持续迭代优化的前后端分离中后台管理系统框架。开箱即用,重视每一处代码规范,重视每一种解决方案细节,持续提供舒适的前、后端开发体验
当前采用的技术栈Spring Boot3Java17、Vue3 & Arco Design & TS & Vite、Sa-Token、MyBatis Plus、Redisson、JetCache、JustAuth、Crane4j、EasyExcel、Liquibase、Hutool 等。
ContiNew Admin Continue New Admin中后台管理框架/脚手架持续以最新流行技术栈构建拥抱变化迭代优化。在社区贡献者的支持和参与下持续发展并源源不断地为企业级项目开发提供助力。当前采用的技术栈Vue3、**Spring Boot 2.7.xJDK8** 、TypeScript、Arco Design Vue、Undertow、Sa-Token、JWT、MariaDB、MyBatis Plus、Redis、Redisson、Easy Excel、Hutool 等
## 项目源码
| | 后端 | 前端 |
| :------ | :----------------------------------------------------------- | :----------------------------------------------------------- |
| Gitee | [continew/continew-admin](https://gitee.com/continew/continew-admin) | [continew/continew-admin-ui](https://gitee.com/continew/continew-admin-ui) |
| GitCode | [continew/continew-admin](https://gitcode.com/continew/continew-admin) | [continew/continew-admin-ui](https://gitcode.com/continew/continew-admin-ui) |
| GitHub | [continew-org/continew-admin](https://github.com/continew-org/continew-admin) | [continew-org/continew-admin-ui](https://github.com/continew-org/continew-admin-ui) |
| 开源平台 | 源码地址 |
| ------------- | ------------------------------------------- |
| GitHub | https://github.com/Charles7c/continew-admin |
| Gitee码云 | https://gitee.com/Charles7c/continew-admin |
## 项目起源
## 主要特性
我热衷于做数据归档,归档后的数据可以提高学习/工作效率,为记忆“减负”,在持续的数据归档中,优质的“沉淀”会带来非匀速、跨越式的学习/工作体验。**数据归档是一件需要持续去做的事情**。
从接触程序代码的第一天,我的程序数据归档也随之开始了,刷过的算法题、笔记、对接各种组件的配置文件,甚至于一些亮眼的样式设计、“如诗”的代码片段。这些数据的沉淀丰富了我的解决方案,提高了我的编程效率,逐渐为各种场景落实成了一个个雏形程序。再后来,我意识到,我归档的这些雏形程序,有一个更为妥贴的名称:**程序框架/脚手架**。
技术的发展,导致这些雏形程序的生命周期很是短暂,它们有别于我归档的其他数据,有时由于工作的原因,没有时间很好的去沉淀它们,在使用时变得越来越不顺手。所以,某段时间,我放弃了维护,而是去采用一些更为成熟的框架。
不过,在陆续几年使用了一些成熟框架后,我前后遇到了一些困难:
1. 代码洁癖想要找到一个**扩展性佳,代码规范良好,开发体验舒适**的框架很不容易,总是差些什么
2. 项目上手困难或是基础版功能不全,需要的全在专业版,亦或者代码阅读性差,文档收费
3. 部分解决方案缺失,已有解决方案也过于偏向样板化,无法形成良好的逻辑闭环
4. 好不容易找到一些相较合适的,没过多久,部分作者可能暂时没法对外发“电”了,随着了解深入,很多 Bug 或新技术趋势还是需要自己研究解决
在工作中,很多想法/设计受限于客户需求、开发工期,必须优先以交付为导向,但一些优秀的实践需要花时间持续进行沉淀,只要我没跳出这个圈子,我还是需要一直去做好程序归档。“种一棵树最好的时间是十年前,其次是现在”,最终,我选择在业余时间更加正视这件事,从头归档沉淀,从添加每一个依赖开始,我希望它能持续的迭代优化、演进,所以我把它命名为 **ContiNewContinue New**。并且这次我选择了开源,我希望它不仅仅能吸收我的需求和沉淀,而是依托开源协作模式,及时发现更多的问题,接受更多的可能性,沉淀更优秀的思考,设计。
## 为什么选我们?
> [!TIP]
> 更为完整的图文描述请查阅[《在线文档》](https://continew.top/admin/guide/why-choose-us.html)。
1.**甄选技术栈:** ContiNewContinue New 项目致力于持续迭代优化,让技术不掉队。在技术选型时,进行深度广泛地调研,从流行度、成熟度和发展潜力等多方面甄选技术栈。
2.**Starter 组件:** 从 v2.1.0 版本开始,抽取并封装后端基础组件及各框架集成配置到 ContiNew Starter 项目,且 **[已发布至 Maven 中央仓库](https://central.sonatype.com/search?q=continew-starter&namespace=top.continew)**,可在你的任意项目中直接引入所需依赖使用。即使你不用脚手架项目,难道能让你搭项目框架更快、更爽、更省力的 Starter 也要 Say No 吗?
3.**CRUD 套件:** 封装通用增删改查套件,适配后端各分层,几分钟即可提供一套 CRUD API包括新增、修改、批量删除、查询详情、分页列表查询、全部列表查询、树型列表查询、导出到 Excel且 API 支持按实际所需开放或扩展。
```java
@Tag(name = "部门管理 API")
@RestController
@CrudRequestMapping(value = "/system/dept", api = {Api.TREE, Api.GET, Api.CREATE, Api.UPDATE, Api.DELETE, Api.EXPORT})
public class DeptController extends BaseController<DeptService, DeptResp, DeptDetailResp, DeptQuery, DeptReq> {}
```
4.**代码生成器:** 提供代码生成器,已配套前、后端代码生成模板,数据表设计完之后,简单配置一下即可生成前、后端 80% 的代码,包含 CRUD API、权限控制、参数校验、接口文档等内容。如果业务不复杂也可能就是 95% 的代码。
5.**改善开发体验:** 持续优化及适配能改善开发体验的组件。
- 适配 ContiNew Starter 各组件,针对 Spring 基础配置、通用解决方案以及流行框架进行了深度封装的 starter 集合,改善你在开发每个 Spring Boot Web 项目的体验。(枚举参数处理、默认线程池、跨域、加密、脱敏、限流、日志、异常及响应通用解决方案等等,更多细节可查看 Starter 源码)
- 适配 Crane4j 数据填充组件,减少因为一个用户名而产生的联表回填;
- 适配 P6Spy SQL 性能分析组件,开发期间方便监控 SQL 执行;
- 适配 TLog 链路追踪组件,方便在杂乱的日志文件中追踪你某次请求的日志记录;
- 适配 JetCache 缓存框架(比 Spring Cache 更强大易用),通过注解声明即可快速实现方法级缓存,极大改善编码式缓存体验,且支持灵活的二级缓存配置、分布式自动刷新等能力;
- 前端适配 Vue DevtoolsVue 官方提供的调试浏览器插件),极大提高 Vue 开发及调试效率
6.**Almost最佳后端规范** 后端严格遵循阿里巴巴 Java 编码规范,注释覆盖率 > 45%,接口参数示例 100%,代码分层使用体验佳,变量、方法命名清晰统一,前端代码也使用严格的 ESLint、StyleLint 等检查。良好的设计,代码复用率极高!写代码时,让你有一种无需多写,理应如此的感觉。我是代码洁癖,我实际写的时候很清楚这到底是不是乱吹。
7.**卓越工程:** 后端采用模块化工程结构,并适配了统一项目版本号、编译项目自动代码格式化、代码混淆等插件,提供了自定义打包部署结构配置(配置文件、三方依赖和主程序分离),提供全套环境及应用的 Docker Compose 部署脚本。为了减少您开发新项目时的改造耗时,项目品牌配置持续进行深度聚合,简单的配置和结构修改即可快速开始独属于你的新项目。
8.**业务脚手架:** 有颜有料,不止是说说而已,持续打磨 UI 设计与色彩主题。提供基于 RBAC 的权限控制、通用数据权限,包含丰富的通用业务功能:第三方登录,邮箱、短信(生产级炸弹漏洞处理方案),个人中心、用户管理、角色管理、部门管理、系统配置(基础站点配置、邮件配置、安全配置)、系统日志、消息中心、通知公告等,设计用心,逻辑合理闭环。
> 一个好的脚手架项目,不仅仅是提供一系列组件集成与配置,也不仅仅是封装一堆好用的工具,还更应该提供一系列通用基础业务解决方案及设计,为初创团队项目减负。
9.**质量与安全:** CI 已集成 Sonar、CodacyPush 即扫描代码质量,定期扫描 CVE 漏洞及时解决潜在问题。封装数据库字段加密、JSON 脱敏、XSS 过滤等工具,提供诸多安全解决方案。
由于篇幅有限,且项目正处于高速发展期,更多功能正在陆续上线(敬请关注仓库或群内动态)。另外像最基本的统一异常、错误处理,基础线程池等配置就不在此赘述,细节优化详情请 clone 代码查看。
> Talk is cheap, show the code.
- :fire: 在 2.x 及以上版本中,下方部分通用基础能力及配置,已抽取到 [ContiNew Starter](https://github.com/Charles7c/continew-starter) 项目,现已发布到 Maven 中央仓库,为 Spring Boot Web 项目开发提供更灵活的助力
- 精选技术栈:使用综合考虑成熟度、流行性、发展潜力较佳的技术栈,包括 Spring Boot、MyBatis Plus、Sa-Token、Hutool 等
- 高效率开发:后端提供了 CRUD 组件,在 Controller 中只需添加一个注解,即可自动生成增、删、改、查、分页、列表、树列表等 API
- 提供代码生成功能,根据用户提供的项目信息和配置,自动生成前后端项目结构、代码文件和部分逻辑代码,提高开发效率
- 一个注解解决一个条件查询,基于注解的通用查询方式,降低拼接 MyBatis Plus QueryWrapper 的烦恼
- 提供一套 Base 基类BaseDO、BaseResp、BaseController、BaseService、扩展版 BaseMapper 等),方便复用和扩展
- 编写或基于 Hutool 扩展部分工具类,提供校验工具和实践,提高开发效率(能 PR 到 Hutool 的已尽量 PR
- 支持 API 级别的功能权限与数据权限,可自定义操作
- 前后端统一异常拦截处理,统一输出异常信息,避免繁琐的异常判断
- 自动初始化数据:通过 Liquibase 管理数据库脚本版本记录,并在系统第一次启动时自动进行数据初始化,无须额外配置导入
- 提供多项实用基础配置例如Jackson 针对日期、通用枚举的序列化、反序列化配置,统一线程池配置等
- 良好的代码、配置文件结构和命名,完善的代码注释甚至包括 Git Commit 信息、接口文档参数示例,遵循阿里巴巴 <a href="https://github.com/Charles7c/continew-admin/blob/dev/code-style/Java%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C(%E9%BB%84%E5%B1%B1%E7%89%88).pdf" target="_blank">《Java开发手册(黄山版)》</a> 的代码规范,保证代码质量和可维护性
- 更多细节及实践,敬请探索与关注
## 系统功能
> [!TIP]
> 更多功能和优化正在赶来💦,最新项目计划进展请进群或关注 [需求墙](https://continew.top/admin/other/feature.html) 和 [更新日志](https://continew.top/admin/other/changelog.html)。
> **Note**
> 更多功能和优化正在赶来💦,最新项目计划进展请关注 [GitHub Project](https://github.com/Charles7c/continew-admin/projects) 和 [CHANGELOG.md](https://github.com/Charles7c/continew-admin/blob/dev/CHANGELOG.md)。
- 仪表盘:提供工作台、分析页,工作台提供功能快捷导航入口、最新公告、动态;分析页提供全面数据可视化能力
- 个人中心:支持基础信息修改、密码修改、邮箱绑定、手机号绑定(并提供行为验证码、短信限流等安全处理)、第三方账号绑定/解绑、头像裁剪上传
- 消息中心:提供站内信消息统一查看、标记已读、全部已读、删除等功能(目前仅支持系统通知消息)、提供个人公告查看
- 用户管理:管理系统用户,包含新增、修改、删除、导入、导出、重置密码、分配角色等功能
- 角色管理:管理系统用户的功能权限及数据权限,包含新增、修改、删除、分配角色等功能
- 菜单管理:管理系统菜单及按钮权限,支持多级菜单,动态路由,包含新增、修改、删除等功能
- 部门管理:管理系统组织架构,包含新增、修改、删除、导出等功能,以树形列表进行展示
- 通知公告:管理系统公告,支持通知范围(所有人、指定用户)、通知方式(系统消息、登录弹窗)、定时发送、置顶设
- 文件管理管理系统文件及文件夹支持上传、下载、预览目前支持图片、音视频、PDF、Word、Excel、PPT、重命名、切换视图列表、网格等功能
- 字典管理:管理系统公用数据字典,例如:消息类型。支持字典标签背景色和排序等配置
- 系统配置:
- 网站配置提供修改系统标题、Logo、favicon、版权信息等基础配置功能以方便用户系统与其自身品牌形象保持一致
- 安全配置:提供密码策略修改,支持丰富的密码策略设定,包括但不限于 `密码有效期``密码重复次数``密码错误锁定账号次数、时间`
- 登录配置:提供验证码开关等登录相关配置
- 邮件配置:提供系统发件箱配置,也支持通过配置文件指定
- 短信配置:提供系统短信服务配置,也支持通过配置文件指定
- 存储配置:管理文件存储配置,支持本地存储、兼容 S3 协议对象存储
- 客户端配置多端PC端、小程序端等认证管理可设置不同的 token 有效期
- 在线用户:管理当前登录用户,可一键踢除下线
- 日志管理:管理系统登录日志、操作日志,支持查看日志详情,包含请求头、响应头等报文信息
- 短信日志:管理系统短信发送日志,支持删除、导出
- 任务管理:管理系统定时任务,包含新增、修改、删除、执行功能,支持 Cron可配置式生成 Cron 表达式) 和固定频率
- 任务日志:管理定时任务执行日志,包含停止、重试指定批次,查询集群各节点的详细输出日志等功能
- 应用管理:管理第三方系统应用 AK、SK包含新增、修改、删除、查看密钥、重置密钥等功能支持设置密钥有效期
- 代码生成:提供根据数据库表自动生成相应的前后端 CRUD 代码的功能,支持同步最新表结构及代码生成预览
- 个人中心:支持基础信息修改、安全设置(密码修改、邮箱绑定、手机号绑定、第三方账号绑定/解绑)、头像裁剪上传、个人操作日志查看
- 用户管理:提供用户的相关配置,新增用户后,默认密码为 123456
- 部门管理:可配置系统组织架构,树形表格展示
- 角色管理:对权限与菜单进行分配,可根据部门设置角色的数据权限
- 菜单管理:已实现菜单动态路由,后端可配置化,支持多级菜单
- 公告管理:提供公告的发布、查看和删除等功能。管理员可以在后台发布公告,并可以设置公告的生效时间、终止时间,以 markdown-it 为内核渲染 Markdown 格式内容显示
- 消息管理:提供消息查看、标记已读、全部已读、删除等功能(适配对接导航栏站内信功能)
- 字典管理:提供对系统公用数据字典的维护,例如:公告类型,支持字典标签背景色和排序等配
- 系统配置提供修改系统标题、Logo、favicon 等基础配置功能,以方便用户系统与其自身品牌形象保持一致(暂未开放高级配置)
- 代码生成:提供根据数据库表自动生成相应的前后端 CRUD 代码的功能
- 在线用户:管理当前登录用户,可一键踢下线
- 日志管理:提供在线用户监控、登录日志监控、操作日志监控和系统日志监控等监控功能
## 系统截图
> [!TIP]
> 受篇幅长度及功能更新频率影响,下方仅为系统 **部分** 功能于 **2024年11月18日** 进行的截图,更多新增功能及细节请登录演示环境或 clone 代码到本地启动查看。
> **Note**
> 受篇幅长度及功能更新频率影响,下方仅为系统 **部分** 功能于 **2023年11月4日** 进行的截图,更多新增功能及细节请登录演示环境或 clone 代码到本地启动查看。
<table border="1" cellpadding="1" cellspacing="1" style="width: 500px">
<tbody>
<tr>
<td><img src=".image/screenshot/000登录页面.png" alt="登录页面" width="1920" /></td>
<td><img src=".image/screenshot/000登录页面-H5.png" alt="登录页面-H5" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/001仪表盘.png" alt="仪表盘" width="1920" /></td>
<td><img src=".image/screenshot/002分析页.png" alt="分析页" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/010个人中心.png" alt="个人中心" width="1920" /></td>
<td><img src=".image/screenshot/013消息中心.png" alt="消息中心" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/011安全设置-修改邮箱.png" alt="安全设置-修改邮箱" width="1920" /></td>
<td><img src=".image/screenshot/012安全设置-修改邮箱-邮箱验证码.png" alt="安全设置-修改邮箱-邮箱验证码" width="1920" /></td>
<td><img src=".image/screenshot/002仪表盘-查看公告.png" alt="仪表盘-查看公告" width="1920" /></td>
<td><img src=".image/screenshot/010个人中心-安全设置.png" alt="个人中心-安全设置" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/060系统管理-系统配置.png" alt="系统管理-系统配置" width="1920" /></td>
<td><img src=".image/screenshot/061系统管理-安全配置.png" alt="系统管理-安全配置" width="1920" /></td>
<td><img src=".image/screenshot/011个人中心-安全设置-修改邮箱.png" alt="个人中心-安全设置-修改邮箱" width="1920" /></td>
<td><img src=".image/screenshot/012个人中心-修改邮箱-发送验证码.png" alt="个人中心-修改邮箱-发送验证码" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/013个人中心-修改邮箱-邮箱验证码.png" alt="个人中心-修改邮箱-邮箱验证码" width="1920" /></td>
<td><img src=".image/screenshot/014个人中心-操作日志.png" alt="个人中心-操作日志" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/015数据可视化-分析页.png" alt="数据可视化-分析页" width="1920" /></td>
<td><img src=".image/screenshot/016数据可视化-多维数据分析页.png" alt="数据可视化-多维数据分析页" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/020系统管理-用户管理-列表.png" alt="系统管理-用户管理-列表" width="1920" /></td>
<td><img src=".image/screenshot/021系统管理-用户管理-新增.png" alt="系统管理-用户管理-新增" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/025系统管理-角色管理-列表.png" alt="系统管理-角色管理-列表" width="1920" /></td>
<td><img src=".image/screenshot/026系统管理-角色管理-新增.png" alt="系统管理-角色管理-新增" width="1920" /></td>
<td><img src=".image/screenshot/025系统管理-部门管理-列表.png" alt="系统管理-部门管理-列表" width="1920" /></td>
<td><img src=".image/screenshot/026系统管理-部门管理-新增.png" alt="系统管理-部门管理-新增" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/030系统管理-菜单管理-列表.png" alt="系统管理-菜单管理-列表" width="1920" /></td>
<td><img src=".image/screenshot/031系统管理-菜单管理-新增.png" alt="系统管理-菜单管理-新增" width="1920" /></td>
<td><img src=".image/screenshot/030系统管理-角色管理-列表.png" alt="系统管理-角色管理-列表" width="1920" /></td>
<td><img src=".image/screenshot/031系统管理-角色管理-新增.png" alt="系统管理-角色管理-新增" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/045系统管理-公告管理-列表.png" alt="系统管理-公告管理-列表" width="1920" /></td>
<td><img src=".image/screenshot/046系统管理-公告管理-修改.png" alt="系统管理-公告管理-修改" width="1920" /></td>
<td><img src=".image/screenshot/035系统管理-菜单管理-列表.png" alt="系统管理-菜单管理-列表" width="1920" /></td>
<td><img src=".image/screenshot/036系统管理-菜单管理-新增.png" alt="系统管理-菜单管理-新增" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/040系统管理-字典管理-列表.png" alt="系统管理-字典管理-列表" width="1920" /></td>
<td><img src=".image/screenshot/041系统管理-字典项管理.png" alt="系统管理-字典项管理" width="1920" /></td>
<td><img src=".image/screenshot/040系统管理-公告管理-列表.png" alt="系统管理-公告管理-列表" width="1920" /></td>
<td><img src=".image/screenshot/041系统管理-公告管理-新增.png" alt="系统管理-公告管理-新增" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/051系统管理-文件管理-列表-2.png" alt="系统管理-文件管理-列表-2" width="1920" /></td>
<td><img src=".image/screenshot/052系统管理-文件管理-查看文档.png" alt="系统管理-文件管理-查看文档" width="1920" /></td>
<td><img src=".image/screenshot/045系统管理-消息管理-列表.png" alt="系统管理-消息管理-列表" width="1920" /></td>
<td><img src=".image/screenshot/046站内信.png" alt="站内信" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/301系统工具-代码生成-配置.png" alt="系统工具-代码生成-配置" width="1920" /></td>
<td><img src=".image/screenshot/302系统工具-代码生成-预览.png" alt="系统工具-代码生成-预览" width="1920" /></td>
<td><img src=".image/screenshot/050系统管理-字典管理-列表.png" alt="系统管理-字典管理-列表" width="1920" /></td>
<td><img src=".image/screenshot/051系统管理-字典管理-新增.png" alt="系统管理-字典管理-新增" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/100系统监控-在线用户.png" alt="系统监控-在线用户" width="1920" /></td>
<td><img src=".image/screenshot/101系统监控-系统日志-登录日志.png" alt="系统监控-系统日志-登录日志" width="1920" /></td>
<td><img src=".image/screenshot/055系统管理-系统配置.png" alt="系统管理-系统配置" width="1920" /></td>
<td><img src=".image/screenshot/056系统管理-系统配置-恢复默认.png" alt="系统管理-系统配置-恢复默认" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/102系统监控-系统日志-操作日志.png" alt="系统监控-系统日志-操作日志" width="1920" /></td>
<td><img src=".image/screenshot/103系统监控-系统日志-操作日志-详情.png" alt="系统监控-系统日志-操作日志-详情" width="1920" /></td>
<td><img src=".image/screenshot/100系统工具-代码生成-列表.png" alt="系统工具-代码生成-列表" width="1920" /></td>
<td><img src=".image/screenshot/101系统工具-代码生成-配置.png" alt="系统工具-代码生成-配置" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/200系统监控-在线用户.png" alt="系统监控-在线用户" width="1920" /></td>
<td><img src=".image/screenshot/201系统监控-操作日志.png" alt="系统监控-操作日志" width="1920" /></td>
</tr>
<tr>
<td><img src=".image/screenshot/202系统监控-系统日志.png" alt="系统监控-系统日志" width="1920" /></td>
<td><img src=".image/screenshot/203系统监控-系统日志-详情.png" alt="系统监控-系统日志-详情" width="1920" /></td>
</tr>
</tbody>
</table>
## 核心技术栈
| 名称 | 版本 | 简介 |
| :----------------------------------------------------------- |:-------------| :----------------------------------------------------------- |
| <a href="https://vuejs.org/" target="_blank">Vue</a> | 3.5.4 | 渐进式 JavaScript 框架,易学易用,性能出色,适用场景丰富的 Web 前端框架。 |
| <a href="https://arco.design/vue/docs/start" target="_blank">Arco Design</a> | 2.57.0 | 字节跳动推出的前端 UI 框架,年轻化的色彩和组件设计。 |
| <a href="https://www.typescriptlang.org/zh/" target="_blank">TypeScript</a> | 5.0.4 | TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript 的基础上添加静态类型定义构建而成。 |
| <a href="https://vite.dev/" target="_blank">Vite</a> | 5.1.5 | 下一代的前端工具链,为开发提供极速响应。 |
| [ContiNew Starter](https://github.com/continew-org/continew-starter) | 2.12.2 | ContiNew Starter 包含了一系列经过企业实践优化的依赖包(如 MyBatis-Plus、SaToken可轻松集成到应用中为开发人员减少手动引入依赖及配置的麻烦为 Spring Boot Web 项目的灵活快速构建提供支持。 |
| <a href="https://spring.io/projects/spring-boot" target="_blank">Spring Boot</a> | 3.3.11 | 简化 Spring 应用的初始搭建和开发过程基于“约定优于配置”的理念使开发人员不再需要定义样板化的配置。Spring Boot 3.0 开始,要求 Java 17 作为最低版本) |
| <a href="https://undertow.io/" target="_blank">Undertow</a> | 2.3.18.Final | 采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。 |
| <a href="https://sa-token.dev33.cn/" target="_blank">Sa-Token + JWT</a> | 1.42.0 | 轻量级 Java 权限认证框架,让鉴权变得简单、优雅。 |
| <a href="https://baomidou.com/" target="_blank">MyBatis Plus</a> | 3.5.8 | MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,简化开发、提高效率。 |
| <a href="https://www.kancloud.cn/tracy5546/dynamic-datasource/2264611" target="_blank">dynamic-datasource-spring-boot-starter</a> | 4.3.1 | 基于 Spring Boot 的快速集成多数据源的启动器。 |
| Hikari | 5.1.0 | JDBC 连接池,号称 “史上最快连接池”SpringBoot 在 2.0 之后,采用的默认数据库连接池就是 Hikari。 |
| <a href="https://dev.mysql.com/downloads/mysql/" target="_blank">MySQL</a> | 8.0.33 | 体积小、速度快、总体拥有成本低,是最流行的关系型数据库管理系统之一。 |
| <a href="https://dev.mysql.com/doc/connector-j/8.0/en/" target="_blank">mysql-connector-j</a> | 8.3.0 | MySQL Java 驱动。 |
| <a href="https://github.com/p6spy/p6spy" target="_blank">P6Spy</a> | 3.9.1 | SQL 性能分析组件。 |
| <a href="https://github.com/liquibase/liquibase" target="_blank">Liquibase</a> | 4.27.0 | 用于管理数据库版本,跟踪、管理和应用数据库变化。 |
| [JetCache](https://github.com/alibaba/jetcache/blob/master/docs/CN/Readme.md) | 2.7.8 | 一个基于 Java 的缓存系统封装,提供统一的 API 和注解来简化缓存的使用。提供了比 SpringCache 更加强大的注解,可以原生的支持 TTL、两级缓存、分布式自动刷新还提供了 Cache 接口用于手工缓存操作。 |
| <a href="https://github.com/redisson/redisson/wiki/Redisson%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D" target="_blank">Redisson</a> | 3.46.0 | 不仅仅是一个 Redis Java 客户端Redisson 充分的利用了 Redis 键值数据库提供的一系列优势,为使用者提供了一系列具有分布式特性的常用工具:分布式锁、限流器等。 |
| <a href="https://redis.io/" target="_blank">Redis</a> | 7.2.3 | 高性能的 key-value 数据库。 |
| [Snail Job](https://snailjob.opensnail.com/) | 1.4.0 | 灵活,可靠和快速的分布式任务重试和分布式任务调度平台。 |
| [X File Storage](https://x-file-storage.xuyanwu.cn/#/) | 2.2.1 | 一行代码将文件存储到本地、FTP、SFTP、WebDAV、阿里云 OSS、华为云 OBS...等其它兼容 S3 协议的存储平台。 |
| <a href="https://sms4j.com/" target="_blank">SMS4J</a> | 3.3.4 | 短信聚合框架,轻松集成多家短信服务,解决接入多个短信 SDK 的繁琐流程。 |
| <a href="https://justauth.cn/" target="_blank">Just Auth</a> | 1.16.7 | 开箱即用的整合第三方登录的开源组件,脱离繁琐的第三方登录 SDK让登录变得 So easy |
| <a href="https://easyexcel.opensource.alibaba.com/" target="_blank">Easy Excel</a> | 3.3.4 | 一个基于 Java 的、快速、简洁、解决大文件内存溢出的 Excel 处理工具。 |
| [AJ-Captcha](https://ajcaptcha.beliefteam.cn/captcha-doc/) | 1.3.0 | Java 行为验证码包含滑动拼图、文字点选两种方式UI支持弹出和嵌入两种方式。 |
| Easy Captcha | 1.6.2 | Java 图形验证码,支持 gif、中文、算术等类型可用于 Java Web、JavaSE 等项目。 |
| [Crane4j](https://createsequence.gitee.io/crane4j-doc/#/) | 2.9.0 | 一个基于注解的,用于完成一切 “根据 A 的 key 值拿到 B再把 B 的属性映射到 A” 这类需求的字段填充框架。 |
| [CosID](https://cosid.ahoo.me/guide/getting-started.html) | 2.12.3 | 旨在提供通用、灵活、高性能的分布式 ID 生成器。 |
| [Graceful Response](https://doc.feiniaojin.com/graceful-response/home.html) | 5.0.4-boot3 | 一个Spring Boot技术栈下的优雅响应处理组件可以帮助开发者完成响应数据封装、异常处理、错误码填充等过程提高开发效率提高代码质量。 |
| <a href="https://doc.xiaominfo.com/" target="_blank">Knife4j</a> | 4.5.0 | 前身是 swagger-bootstrap-ui集 Swagger2 和 OpenAPI3 为一体的增强解决方案。 |
| [OpenFeign](https://springdoc.cn/spring-cloud-openfeign/) | 13.5 | Spring Cloud OpenFeign 是一种基于 Spring Cloud 的声明式 REST 客户端,它简化了与 HTTP 服务交互的过程。 |
| <a href="https://www.hutool.cn/" target="_blank">Hutool</a> | 5.8.37 | 小而全的 Java 工具类库,通过静态方法封装,降低相关 API 的学习成本,提高工作效率,使 Java 拥有函数式语言般的优雅,让 Java 语言也可以“甜甜的”。 |
| <a href="https://projectlombok.org/" target="_blank">Lombok</a> | 1.18.36 | 在 Java 开发过程中用注解的方式,简化了 JavaBean 的编写,避免了冗余和样板式代码,让编写的类更加简洁。 |
## 快速开始
> [!TIP]
> 更详细的流程,请查看在线文档[《快速开始》](https://continew.top/admin/guide/quick-start.html)
> **Note**
> 下方步骤有重叠部分,无需重复执行
### 后端
```bash
# 1.克隆本项目
git clone https://github.com/continew-org/continew-admin.git
git clone https://github.com/Charles7c/continew-admin.git
# 2.在 IDEIntelliJ IDEA/Eclipse中打开本项目
@@ -271,178 +167,282 @@ git clone https://github.com/continew-org/continew-admin.git
# 5.1.1 服务器安装好 docker 及 docker-compose参考https://blog.charles7c.top/categories/fragments/2022/10/31/CentOS%E5%AE%89%E8%A3%85Docker
# 5.1.2 执行 mvn package 进行项目打包,将 target/app 目录下的所有内容放到 /docker/continew-admin 目录下
# 5.1.3 将 docker 目录上传到服务器 / 目录下并授权chmod -R 777 /docker
# 5.1.4 修改 docker-compose.yml 中的 MySQL 配置、Redis 配置、continew-admin-server 配置、Nginx 配置
# 5.1.4 修改 docker-compose.yml 中的 MariaDB 配置、Redis 配置、continew-admin-server 配置、Nginx 配置
# 5.1.5 执行 docker-compose up -d 创建并后台运行所有容器
# 5.2 其他方式部署
```
### 前端
```bash
# 1.克隆本项目
git clone https://github.com/Charles7c/continew-admin.git
# 2.在 IDEVisual Studio Code/WebStorm中打开前端项目 continew-admin-ui
# 3.安装 pnpm配置淘宝源
npm install -g pnpm
pnpm config set registry https://registry.npm.taobao.org
# 4.安装依赖
pnpm i
# 5.启动程序
# 5.1 启动成功:访问 http://localhost:5173/
pnpm dev
# 6.部署
# 6.1 Docker 部署
# 6.1.1 服务器安装好 docker 及 docker-compose参考https://blog.charles7c.top/categories/fragments/2022/10/31/CentOS%E5%AE%89%E8%A3%85Docker
# 6.1.2 执行 pnpm build 进行项目打包,将 dist 目录下的所有文件放到 /docker/continew-admin/web 目录下
# 6.1.3 将 docker 目录上传到服务器 / 目录下并授权chmod -R 777 /docker
# 6.1.4 修改 docker-compose.yml 中的 MariaDB 配置、Redis 配置、continew-admin-server 配置、Nginx 配置
# 6.1.5 执行 docker-compose up -d 创建并后台运行所有容器
# 6.2 其他方式部署
```
## 核心技术栈
| 名称 | 版本 | 简介 |
| :----------------------------------------------------------- |:-------------| :----------------------------------------------------------- |
| <a href="https://cn.vuejs.org/" target="_blank">Vue</a> | 3.3.4 | 渐进式 JavaScript 框架,易学易用,性能出色,适用场景丰富的 Web 前端框架。 |
| <a href="https://www.typescriptlang.org/zh/" target="_blank">TypeScript</a> | 4.9.5 | TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript 的基础上添加静态类型定义构建而成。 |
| <a href="https://arco.design/vue/docs/start" target="_blank">Arco Design Vue</a> | 2.52.0 | 字节跳动推出的前端 UI 框架,年轻化的色彩和组件设计。 |
| <a href="https://spring.io/projects/spring-boot" target="_blank">Spring Boot</a> | 2.7.16 | 简化新 Spring 应用的初始搭建以及开发过程。 |
| <a href="https://undertow.io/" target="_blank">Undertow</a> | 2.2.26.Final | 采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。 |
| <a href="https://sa-token.dev33.cn/" target="_blank">Sa-Token + JWT</a> | 1.36.0 | 轻量级 Java 权限认证框架,让鉴权变得简单、优雅。 |
| <a href="https://mariadb.org/" target="_blank">MariaDB</a> | 10.10.2 | MySQL 的一个分支,主要由开源社区在维护,完全兼容 MySQL包括 API 和命令行,能轻松成为 MySQL 的代替品。 |
| <a href="https://baomidou.com/" target="_blank">MyBatis Plus</a> | 3.5.3.2 | MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,简化开发、提高效率。 |
| <a href="https://www.kancloud.cn/tracy5546/dynamic-datasource/2264611" target="_blank">dynamic-datasource-spring-boot-starter</a> | 3.6.1 | 基于 Spring Boot 的快速集成多数据源的启动器。 |
| Hikari | 4.0.3 | JDBC 连接池,号称 “史上最快连接池”SpringBoot 在 2.0 之后,采用的默认数据库连接池就是 Hikari。 |
| <a href="https://dev.mysql.com/doc/connector-j/8.0/en/" target="_blank">mysql-connector-j</a> | 8.0.33 | MySQL Java 驱动。 |
| <a href="https://github.com/p6spy/p6spy" target="_blank">P6Spy</a> | 3.9.1 | SQL 性能分析组件。 |
| <a href="https://github.com/liquibase/liquibase" target="_blank">Liquibase</a> | 4.9.1 | 用于管理数据库版本,跟踪、管理和应用数据库变化。 |
| <a href="https://redis.io/" target="_blank">Redis</a> | 6.2.7 | 高性能的 key-value 数据库。 |
| <a href="https://github.com/redisson/redisson/wiki/Redisson%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D" target="_blank">Redisson</a> | 3.20.1 | 不仅仅是一个 Redis Java 客户端,同其他 Redis Java 客户端有着很大的区别,相比之下其他客户端提供的功能还仅仅停留在作为数据库驱动层面上,比如仅针对 Redis 提供连接方式,发送命令和处理返回结果等。而 Redisson 充分的利用了 Redis 键值数据库提供的一系列优势,基于 Java 实用工具包中常用接口,为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务,更进一步简化了分布式环境中程序相互之间的协作。 |
| <a href="https://sms4j.com/" target="_blank">SMS4J</a> | 3.0.4 | 短信聚合框架,轻松集成多家短信服务,解决接入多个短信 SDK 的繁琐流程。 |
| <a href="https://justauth.cn/" target="_blank">Just Auth</a> | 1.16.5 | 开箱即用的整合第三方登录的开源组件,脱离繁琐的第三方登录 SDK让登录变得 So easy |
| <a href="https://easyexcel.opensource.alibaba.com/" target="_blank">Easy Excel</a> | 3.3.2 | 一个基于 Java 的、快速、简洁、解决大文件内存溢出的 Excel 处理工具。 |
| Easy Captcha | 1.6.2 | Java 图形验证码,支持 gif、中文、算术等类型可用于 Java Web、JavaSE 等项目。 |
| <a href="https://doc.xiaominfo.com/" target="_blank">Knife4j</a> | 4.3.0 | 前身是 swagger-bootstrap-ui集 Swagger2 和 OpenAPI3 为一体的增强解决方案。本项目使用的是 <a href="https://gitee.com/xiaoym/swagger-bootstrap-ui-demo/tree/master/knife4j-springdoc-openapi-demo" target="_blank">knife4j-openapi3-spring-boot-starter</a> 基于 OpenAPI3 规范,在 Spring Boot < 3.0.0-M1 的单体架构下可以直接引用此 starter该模块包含了 UI 部分底层基于 springdoc-openapi 项目 |
| <a href="https://www.hutool.cn/" target="_blank">Hutool</a> | 5.8.22 | 小而全的 Java 工具类库,通过静态方法封装,降低相关 API 的学习成本,提高工作效率,使 Java 拥有函数式语言般的优雅,让 Java 语言也可以“甜甜的”。 |
| <a href="https://projectlombok.org/" target="_blank">Lombok</a> | 1.18.30 | 在 Java 开发过程中用注解的方式,简化了 JavaBean 的编写,避免了冗余和样板式代码,让编写的类更加简洁。 |
## 项目结构
> [!TIP]
> 后端采用按功能拆分模块的开发方式,下方项目目录结构是按照模块的层次顺序进行介绍的,实际 IDE 中 `continew-admin-common` 模块会因为字母排序原因排在上方。
### 后端
采用按功能拆分模块的开发方式,项目目录结构如下:
> **Note**
> 下方项目目录结构是按照模块的层次顺序进行介绍的,实际 IDE 中 `continew-admin-common` 模块会因为字母排序原因排在上方。
```bash
continew-admin # 全局通用项目配置及依赖版本管理
├─ continew-admin-webapi # API 模块(存放 Controller 层代码,打包部署的模块)
│ └─ src
│ └─ main
│ ├─ java # 工程源文件代码目录
│ │ └─ top
│ │ └─ charles7c
│ │ └─ cnadmin
│ │ ├─ webapi
│ │ │ └─ controller
│ │ │ ├─ auth # 认证相关 API
│ │ │ ├─ common # 公共相关 API例如验证码 API 等)
│ │ │ ├─ monitor # 系统监控相关 API
│ │ │ ├─ system # 系统管理相关 API
│ │ │ └─ tool # 系统工具相关 API
│ │ └─ ContinewAdminApplication.java # 启动入口
│ └─ resources # 工程配置目录
│ ├─ db.changelog # 数据库脚本文件
│ │ ├─ v1.0.0 # v1.0.0 版本数据库脚本文件
│ │ ├─ v1.1.0 # v1.1.0 版本数据库脚本文件
│ │ ├─ v1.2.0 # v1.2.0 版本数据库脚本文件
│ │ └─ v1.3.0 # v1.3.0 版本数据库脚本文件
│ └─ templates # 模板文件
│ └─ mail # 邮件模板
├─ continew-admin-monitor # 系统监控模块(存放系统监控模块相关功能,例如:日志管理、服务监控等)
│ └─ src
│ └─ main
│ ├─ java # 工程源文件代码目录
│ │ └─ top
│ │ └─ charles7c
│ │ └─ cnadmin
│ │ └─ monitor
│ │ ├─ annotation # 系统监控相关注解
│ │ ├─ config # 系统监控相关配置
│ │ │ └─ properties # 系统监控相关配置属性
│ │ ├─ enums # 系统监控相关枚举
│ │ ├─ filter # 系统监控相关过滤器
│ │ ├─ interceptor # 系统监控相关拦截器
│ │ ├─ mapper # 系统监控相关 Mapper
│ │ ├─ model # 系统监控相关模型
│ │ │ ├─ entity # 系统监控相关实体对象
│ │ │ ├─ query # 系统监控相关查询条件
│ │ │ └─ resp # 系统监控相关响应对象Response
│ │ └─ service # 系统监控相关业务接口及实现类
│ │ └─ impl # 系统监控相关业务实现类
│ └─ resources # 工程配置目录
│ └─ mapper # MyBatis Mapper XML 文件目录
├─ continew-admin-system # 系统管理模块(存放系统管理模块相关功能,例如:部门管理、角色管理、用户管理等)
│ └─ src
│ └─ main
│ ├─ java # 工程源文件代码目录
│ │ └─ top
│ │ └─ charles7c
│ │ └─ cnadmin
│ │ ├─ auth # 系统认证相关业务及配置
│ │ │ ├─ config # 系统认证相关配置
│ │ │ │ └─ satoken # Sa-Token 配置
│ │ │ ├─ model # 系统认证相关模型
│ │ │ │ ├─ query # 系统认证相关查询条件
│ │ │ │ ├─ req # 系统认证相关请求对象
│ │ │ │ └─ resp # 系统认证相关响应对象
│ │ │ └─ service # 系统认证相关业务接口及实现类
│ │ │ └─ impl # 系统认证相关业务实现类
│ │ └─ system # 系统管理相关业务及配置
│ │ ├─ enums # 系统管理相关枚举
│ │ ├─ mapper # 系统管理相关 Mapper
│ │ ├─ model # 系统管理相关模型
│ │ │ ├─ entity # 系统管理相关实体对象
│ │ │ ├─ query # 系统管理相关查询条件
│ │ │ ├─ req # 系统管理相关请求对象
│ │ │ └─ resp # 系统管理相关响应对象
│ │ └─ service # 系统管理相关业务接口及实现类
│ │ └─ impl # 系统管理相关业务实现类
│ └─ resources # 工程配置目录
│ └─ mapper # MyBatis Mapper XML 文件目录
├─ continew-admin-tool # 系统工具模块(存放系统工具模块相关功能,例如:代码生成、文件管理等)
│ └─ src
│ └─ main
│ ├─ java # 工程源文件代码目录
│ │ └─ top
│ │ └─ charles7c
│ │ └─ cnadmin
│ │ └─ tool
│ │ ├─ config # 系统工具相关配置
│ │ │ └─ properties # 系统工具相关配置属性
│ │ ├─ enums # 系统工具相关枚举
│ │ ├─ mapper # 系统工具相关 Mapper
│ │ ├─ model # 系统工具相关模型
│ │ │ ├─ entity # 系统工具相关实体对象
│ │ │ ├─ query # 系统工具相关查询条件
│ │ │ ├─ req # 系统工具相关请求对象
│ │ │ └─ resp # 系统工具相关响应对象
│ │ ├─ service # 系统工具相关业务接口及实现类
│ │ │ └─ impl # 系统工具相关业务实现类
│ │ └─ util # 系统工具相关工具类
│ └─ resources # 工程配置目录
│ ├─ mapper # MyBatis Mapper XML 文件目录
│ └─ templates # 模板文件
│ └─ generator # 代码生成器模板
├─ continew-admin-common # 公共模块(存放公共工具类,公共配置等)
│ └─ src
│ └─ main
│ └─ java # 工程源文件代码目录
│ └─ top
│ └─ charles7c
│ └─ cnadmin
│ └─ common
│ ├─ annotation # 公共注解
│ ├─ base # 公共基类
│ ├─ config # 公共配置
│ │ ├─ easyexcel # Easy Excel 配置
│ │ ├─ jackson # Jackson 配置
│ │ ├─ mybatis # MyBatis Plus 配置
│ │ ├─ threadpool # 线程池配置
│ │ └─ properties # 公共配置属性
│ ├─ constant # 公共常量
│ ├─ enums # 公共枚举
│ ├─ exception # 公共异常
│ ├─ handler # 公共处理器
│ ├─ model # 公共模型
│ │ ├─ dto # 公共 DTOData Transfer Object
│ │ ├─ query # 公共查询条件
│ │ ├─ req # 公共请求对象
│ │ └─ resp # 公共响应对象
│ ├─ service # 公共业务接口
│ └─ util # 公共工具类
│ ├─ helper # 公共 Helper助手
│ ├─ holder # 公共 Holder持有者
│ └─ validate # 公共校验器(参数校验,业务校验)
```
### 前端
```bash
continew-admin
─ continew-webapiAPI 及打包部署模块)
├─ src
├─ main
│ │ ├─ java/top/continew/admin
│ │ │ ├─ config (配置)
│ │ ├─ controller
│ │ │ │ ├─ auth(系统认证相关 API
│ │ │ │ ├─ common(通用相关 API
│ │ │ │ ├─ monitor(系统监控相关 API
│ │ │ │ ├─ system(系统管理相关 API
│ │ │ │ └─ tool(系统工具相关 API
│ │ContiNewAdminApplication.javaContiNew Admin 启动程序)
│ │ resources
│ │ ├─ config核心配置目录
│ │ │ ├─ application-dev.yml开发环境配置文件
│ │ │ │ ├─ application-prod.yml生产环境配置文件
│ │ └─ application.yml通用配置文件
│ │ ├─ db/changelogLiquibase 数据脚本配置目录)
├─ mysqlMySQL 数据库初始 SQL 脚本目录)
├─ postgresqlPostgreSQL 数据库初始 SQL 脚本目录)
│ └─ db.changelog-master.yamlLiquibase 变更记录文件)
├─ templates模板配置目录例如邮件模板
│ ├─ banner.txtBanner 配置文件)
│ └─ logback-spring.xml日志配置文件
test测试相关代码目录
pom.xml包含打包相关配置
├─ continew-module-system系统管理模块存放系统管理相关业务功能例如部门管理、角色管理、用户管理等
│ ├─ src
│ │ ├─ main
│ │ ├─ java/top/continew/admin
│ │ ├─ auth系统认证相关业务
│ │ │ │ ├─ model系统认证相关模型
│ │ │ │ │ ├─ query系统认证相关查询条件
│ │ │ │ ├─ req系统认证相关请求对象Request
│ │ │ │ resp系统认证相关响应对象Response
│ │ │ │ └─ service系统认证相关业务接口及实现类
│ │ │ └─ system系统管理相关业务
│ │ │ ├─ config系统管理相关配置
│ │ ├─ enums系统管理相关枚举
│ │ ├─ mapper系统管理相关 Mapper
│ │ ├─ model系统管理相关模型
│ │ ├─ entity系统管理相关实体对象
│ │ │ ├─ query系统管理相关查询条件
│ │ ├─ req系统管理相关请求对象Request
│ │ │ └─ resp系统管理相关响应对象Response
│ │ ─ service系统管理相关业务接口及实现类
│ │ └─ util系统管理相关工具类
resources
└─ mapper系统管理相关 Mapper XML 文件目录)
test测试相关代码目录
└─ pom.xml
├─ continew-plugin插件模块存放代码生成、任务调度等扩展模块后续会进行插件化改造
├─ continew-plugin-schedule任务调度插件模块
src
│ │ │ ├─ main/java/top/continew/admin/schedule
│ │ │ │ ├─ api任务调度中心相关 API
│ │ │ │ ├─ config任务调度相关配置
│ │ │ │ ├─ constant任务调度相关常量
│ │ │ │ ├─ enums任务调度相关枚举
│ │ │ │ ├─ model任务调度相关模型
│ │ │ │ │ ├─ query任务调度相关查询条件
│ │ │ │ │ ├─ req任务调度相关请求对象Request
│ │ │ │ │ └─ resp任务调度相关响应对象Response
│ │ │ │ └─ service代码生成器相关业务接口及实现类
│ │ │ └─ test测试相关代码目录
│ │ └─ pom.xml
│ ├─ continew-plugin-open能力开放插件模块
│ │ ├─ src
│ │ │ ├─ main/java/top/continew/admin/open
│ │ │ │ ├─ mapper代码生成器相关 Mapper
│ │ │ │ ├─ model能力开放相关模型
│ │ │ │ │ ├─ entity能力开放相关实体对象
│ │ │ │ │ ├─ query能力开放相关查询条件
│ │ │ │ │ ├─ req能力开放相关请求对象Request
│ │ │ │ │ └─ resp能力开放相关响应对象Response
│ │ │ │ └─ service能力开放相关业务接口及实现类
│ │ │ └─ test测试相关代码目录
│ │ └─ pom.xml
│ ├─ continew-plugin-generator代码生成器插件模块
│ │ ├─ src
│ │ │ ├─ main
│ │ │ │ ├─ java/top/continew/admin/generator
│ │ │ │ │ ├─ config代码生成器相关配置
│ │ │ │ │ ├─ enums代码生成器相关枚举
│ │ │ │ │ ├─ mapper代码生成器相关 Mapper
│ │ │ │ │ ├─ model代码生成器相关模型
│ │ │ │ │ │ ├─ entity代码生成器相关实体对象
│ │ │ │ │ │ ├─ query代码生成器相关查询条件
│ │ │ │ │ │ ├─ req代码生成器相关请求对象Request
│ │ │ │ │ │ └─ resp代码生成器相关响应对象Response
│ │ │ │ │ └─ service代码生成器相关业务接口及实现类
│ │ │ │ └─ resources
│ │ │ │ ├─ templates/generator代码生成相关模板目录
│ │ │ │ ├─ application.yml代码生成配置文件
│ │ │ │ └─ generator.properties代码生成类型映射配置文件
│ │ │ └─ test测试相关代码目录
│ │ └─ pom.xml
│ └─ pom.xml
├─ continew-common公共模块存放公共工具类公共配置等
│ ├─ src
│ │ ├─ main/java/top/continew/admin/common
│ │ │ ├─ config公共配置
│ │ │ ├─ constant公共常量
│ │ │ ├─ enums公共枚举
│ │ │ ├─ model公共模型
│ │ │ │ ├─ dto公共 DTOData Transfer Object
│ │ │ │ ├─ req公共请求对象Request
│ │ │ │ └─ resp公共响应对象Response
│ │ │ └─ util公共工具类
│ │ └─ test测试相关代码目录
│ └─ pom.xml
├─ continew-extension扩展模块
│ ├─ continew-extension-schedule-server任务调度服务端模块实际开发时如果是公司统一提供环境可直接删除本模块
│ │ ├─ src
│ │ │ ├─ main
│ │ │ │ ├─ java/top/continew/admin/extension/schedule
│ │ │ │ │ └─ ScheduleServerApplication.java任务调度服务端启动程序
│ │ │ │ └─ resources
│ │ │ │ ├─ config核心配置目录
│ │ │ │ │ ├─ application-dev.yml开发环境配置文件
│ │ │ │ │ ├─ application-prod.yml生产环境配置文件
│ │ │ │ │ └─ application.yml通用配置文件
│ │ │ │ ├─ db/changelogLiquibase 数据脚本配置目录)
│ │ │ │ │ ├─ mysqlMySQL 数据库初始 SQL 脚本目录)
│ │ │ │ │ ├─ postgresqlPostgreSQL 数据库初始 SQL 脚本目录)
│ │ │ │ │ └─ db.changelog-master.yamlLiquibase 变更记录文件)
│ │ │ │ └─ logback-spring.xml日志配置文件
│ │ │ └─ test测试相关代码目录
│ │ └─ pom.xml
│ └─ pom.xml
├─ .githubGitHub 相关配置目录,实际开发时直接删除)
├─ .idea
│ └─ icon.pngIDEA 项目图标,实际开发时直接删除)
├─ .image截图目录实际开发时直接删除
├─ .style代码格式、License文件头相关配置目录实际开发时根据需要取舍删除时注意删除 spotless 插件配置)
├─ .gitignoreGit 忽略文件相关配置文件)
├─ docker项目部署相关配置目录实际开发时可备份后直接删除
├─ LICENSE开源协议文件
├─ CHANGELOG.md更新日志文件实际开发时直接删除
├─ README.md项目 README 文件,实际开发时替换为真实内容)
├─ lombok.configLombok 全局配置文件)
└─ pom.xml包含版本锁定及全局插件相关配置
─ continew-admin-ui # 前端项目
├─ config # 全局 Vite 配置
├─ public # 公共静态资源favicon.ico、logo.svg
├─ src
│ ├─ api # 请求接口
│ │ ├─ demo # 示例模块
│ │ ├─ auth # 认证模块
│ │ ├─ common # 公共模块
│ │ ├─ monitor # 系统监控模块
│ │ ├─ system # 系统管理模块
│ │ └─ tool # 系统工具模块
assets # 静态资源
│ │ icons # 图标资源
│ │ ├─ images # 图片资源
│ │ └─ style # 样式资源
│ ├─ components # 通用业务组件
│ ├─ config # 全局配置(包含 echarts 主题)
│ │ └─ settings.json # 配置文件
├─ directives # 指令集(如需,可自行补充)
├─ hooks # 全局 hooks
├─ layout # 布局
├─ locale # 国际化语言包
├─ mock # 模拟数据
├─ router # 路由配置
store # 状态管理中心
types # TypeScript 类型
│ ├─ utils # 工具库
│ ├─ views # 页面模板
│ │ ├─ demo # Arco Design 相关示例模块
│ │ ├─ dashboard # 仪表盘模块
│ │ ├─ login # 登录模块
│ │ ├─ monitor # 系统监控模块
│ │ │ ├─ log # 日志管理
│ │ │ │ ├─ login # 登录日志
│ │ │ │ operation # 操作日志
│ │ │ │ └─ system # 系统日志
│ │ │ └─ online # 在线用户
│ │ └─ system # 系统管理模块
│ │ ├─ announcement # 公告管理
│ │ ├─ config # 系统配置
│ │ ├─ dept # 部门管理
│ │ ├─ dict # 字典管理
│ │ ├─ menu # 菜单管理
│ │ ├─ message # 消息管理
│ │ ├─ role # 角色管理
│ │ user # 用户模块
│ │ └─ center # 个人中心
App.vue
│ └─ main.ts # 入口文件
.env.development
├─ .env.production
├─ index.html
├─ package.json
tsconfig.json
```
## 贡献指南
## 贡献代码
ContiNew Admin 致力于提供开箱即用,持续舒适的开发体验。作为一个开源项目Creator 的初心是希望 ContiNew Admin 依托开源协作模式,提升技术透明度、放大集体智慧、共创优秀实践,源源不断地为企业级项目开发提供助力
我们非常欢迎广大社区用户为 ContiNew Admin **贡献(开发,测试、文档、答疑等)** 或优化代码,欢迎各位感兴趣的小伙伴儿,[添加微信](https://continew.top/discussion.html) 讨论或认领任务。
ContiNew Admin 致力于持续以最新流行技术栈构建,拥抱变化,迭代优化。作为一个开源项目Creator 的初心是希望 ContiNew Admin 在社区贡献者的支持和参与下,持续发展并源源不断地为企业级项目开发提供助力。我们非常欢迎广大社区用户为 ContiNew Admin 贡献或优化代码
### 分支说明
ContiNew Admin 的分支目前分为下个大版本的开发分支和上个大版本的维护分支PR 前请注意对应分支是否处于维护状态,版本支持情况请查看 [更新日志/版本支持](https://continew.top/admin/other/changelog.html#%E7%89%88%E6%9C%AC%E6%94%AF%E6%8C%81)。
ContiNew Admin 的分支目前分为下个大版本的开发分支和上个大版本的维护分支PR 前请注意对应分支是否处于维护状态,版本支持情况请查看 [更新日志/版本支持](https://doc.charles7c.top/other/changelog.html#%E7%89%88%E6%9C%AC%E6%94%AF%E6%8C%81)。
| 分支 | 说明 |
| ----- | ------------------------------------------------------------ |
| dev | 开发分支,默认为下个大版本的 SNAPSHOT 版本,接受新功能或新功能优化 PR |
| x.x.x | 维护分支,在 vx.x.x 版本维护期终止前(一般为下个大版本发布前),用于修复上个版本的 Bug只接受已有功能修复不接受新功能 PR |
### 贡献代码
### 流程步骤
如果您想提交新功能或优化现有代码,可以按照以下步骤操作:
@@ -450,45 +450,63 @@ ContiNew Admin 的分支目前分为下个大版本的开发分支和上个大
2. 然后,将 fork 过来的项目(即您的项目)克隆到本地
3. 切换到当前仍在维护的分支(请务必充分了解分支使用说明,可进群联系维护者确认)
4. 开始修改代码,修改完成后,将代码 commit 并 push 到您的远程仓库
5. 在 Gitee 或 Github 上新建 pull requestpr选择好源和目标按模板要求填写说明信息后提交即可多多参考 [已批准合并的 pr 记录](https://github.com/continew-org/continew-admin/pulls?q=is%3Apr+is%3Amerged),会大大增加批准合并率)
5. 在 Gitee 或 Github 上新建 pull requestpr选择好源和目标按模板要求填写说明信息后提交即可多多参考 [已批准合并的 pr 记录](https://github.com/Charles7c/continew-admin/pulls?q=is%3Apr+is%3Amerged),会大大增加批准合并率)
6. 最后,耐心等待维护者合并您的请求即可
请记住,如果您有任何疑问或需要帮助,我们将随时提供支持。
> [!IMPORTANT]
> **IMPORTANT**
> 欢迎大家为 ContiNew Admin 贡献代码,我们非常感谢您的支持!为了更好地管理项目,维护者有一些要求:
>
> 1. 请确保代码、配置文件的结构和命名规范良好,完善的代码注释甚至包括接口文档参数示例,并遵循阿里巴巴的 <a href="https://github.com/continew-org/continew-admin/blob/dev/.style/Java%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C(%E9%BB%84%E5%B1%B1%E7%89%88).pdf" target="_blank">《Java开发手册(黄山版)》</a> 中的代码规范,保证代码质量和可维护性
> 1. 请确保代码、配置文件的结构和命名规范良好,完善的代码注释甚至包括接口文档参数示例,并遵循阿里巴巴的 <a href="https://github.com/Charles7c/continew-admin/blob/dev/code-style/Java%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C(%E9%BB%84%E5%B1%B1%E7%89%88).pdf" target="_blank">《Java开发手册(黄山版)》</a> 中的代码规范,保证代码质量和可维护性
> 2. 在提交代码前,请按照 [Angular 提交规范](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular) 编写 commit 的 message建议在 IntelliJ IDEA 中下载并安装 Git Commit Template 插件,以便按照规范进行 commit
> 3. 提交代码之前,请关闭所有代码窗口,执行 `mvn compile` 命令(代码格式化插件会在项目编译时对全局代码进行格式修正),编译通过后,不要再打开查看任何代码窗口,直接提交即可,以免不同的 IDE 配置会自动进行代码格式化
> 3. 提交代码之前,请关闭所有代码窗口,执行 mvn compile 命令(项目已配置代码格式化插件,编译通过的同时也会自动进行代码格式化),编译通过后,不要再打开查看任何代码窗口,直接提交即可,以免不同的 IDE 配置会自动进行代码格式化
## 反馈交流
欢迎各位小伙伴儿扫描下方二维码加入项目交流群,与项目维护团队及其他大佬用户实时交流讨论。
💬 欢迎各位小伙伴儿扫描下方二维码加好友,备注 `cnadmin`,拉你进群,探讨技术、提提需求~
加入交流群后,你将会:
- 第一时间收到框架动态
- 第一时间收到框架更新通知
- 第一时间收到框架 Bug 通知
- 和众多大佬互相 (huá shuǐ) 交流 (mō yú)
<div align="left">
<img src=".image/qrcode.jpg" alt="二维码" height="230px" />
<img src=".image/qrcode.jpg" alt="二维码" width="230px" />
</div>
<details>
<summary>无加群意愿</summary>
💬 如无加群意愿,欢迎在 <a href="https://github.com/Charles7c/continew-admin/issues" target="_blank">Issues</a> 中反馈交流~ 🍻
</details>
## 鸣谢
### 鸣谢
感谢参与贡献的每一位小伙伴🥰
<a href="https://github.com/continew-org/continew-admin/graphs/contributors">
<a href="https://github.com/Charles7c/continew-admin/graphs/contributors">
<img src="https://opencollective.com/continew-admin/contributors.svg?width=890&button=false" alt="contributors" />
</a>
### 特别鸣谢
- 感谢 <a href="https://www.jetbrains.com/" target="_blank">JetBrains</a> 提供的 <a href="https://jb.gg/OpenSourceSupport" target="_blank">非商业开源软件开发授权</a>
- 感谢 <a href="https://github.com/baomidou/mybatis-plus" target="_blank">MyBatis Plus</a><a href="https://github.com/dromara/sa-token" target="_blank">Sa-Token</a><a href="https://github.com/alibaba/jetcache" target="_blank">JetCache</a><a href="https://github.com/opengoofy/crane4j" target="_blank">Crane4j</a><a href="https://github.com/xiaoymin/knife4j" target="_blank">Knife4j</a><a href="https://github.com/dromara/hutool" target="_blank">Hutool</a> 等开源组件作者为国内开源世界作出的贡献
- 感谢 <a href="https://www.jetbrains.com/" target="_blank">JetBrains</a> 提供的 <a href="https://www.jetbrains.com/shop/eform/opensource" target="_blank">非商业开源软件开发授权</a>
- 感谢 <a href="http://pro.arco.design/" target="_blank">Arco Design Pro</a> 开箱即用的中后台前端解决方案
- 感谢 <a href="https://github.com/baomidou/mybatis-plus" target="_blank">MyBatis Plus</a><a href="https://github.com/dromara/sa-token" target="_blank">Sa-Token</a><a href="https://github.com/alibaba/easyexcel" target="_blank">Easy Excel</a><a href="https://github.com/xiaoymin/knife4j" target="_blank">Knife4j</a><a href="https://github.com/dromara/hutool" target="_blank">Hutool</a> 等国产开源组件作者为国内开源世界作出的贡献
- 感谢 <a href="https://github.com/elunez/eladmin" target="_blank">ELADMIN</a><a href="https://github.com/yangzongzhuan/RuoYi-Vue3" target="_blank">RuoYi-Vue3</a><a href="https://github.com/dromara/RuoYi-Vue-Plus" target="_blank">RuoYi-Vue-Plus</a>,致敬各位作者为开源脚手架领域作出的贡献
- e.g. 脱胎于 ELADMIN 项目开源的 QueryHelper 组件
- e.g. 参考 RuoYi-Vue3 前端项目的 Vue3 编码风格和规范
- e.g. 使用 RuoYi-Vue-Plus 项目封装的 SaToken 相关认证鉴权配置等
- 感谢项目使用或未使用到的每一款开源组件,致敬各位开源先驱 :fire:
## License
- 遵循 <a href="https://github.com/continew-org/continew-admin/blob/dev/LICENSE" target="_blank">Apache-2.0</a> 开源许可协议
- 遵循 <a href="https://github.com/Charles7c/continew-admin/blob/dev/LICENSE" target="_blank">Apache-2.0</a> 开源许可协议
- Copyright © 2022-present <a href="https://blog.charles7c.top" target="_blank">Charles7c</a>
## GitHub Star 趋势

8
code-style/STYLE.md Normal file
View File

@@ -0,0 +1,8 @@
## 统一代码风格
如果要编辑本项目,一定要统一代码风格
### 统一方案
本工程代码遵守阿里巴巴 [p3c](https://github.com/alibaba/p3c) 规范,在代码开发前建议:
* 安装阿里巴巴规约插件,用于提早发现不规范代码,具体安装方法参照:[p3c](https://github.com/alibaba/p3c),里面有 EclipseIntelliJ IDEA 的安装方法

View File

@@ -1,380 +1,496 @@
<?xml version="1.0" encoding="utf-8"?>
<profiles version="21">
<profile kind="CodeFormatterProfile" name="P3C-CodeStyle" version="21">
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- 生成当前格式化配置文件参照https://github.com/diffplug/spotless/blob/main/ECLIPSE_SCREENSHOTS.md -->
<profiles version="12">
<profile kind="CodeFormatterProfile" name="P3C-CodeStyle" version="13">
<!-- 可变参数的... IDEA 没有对应的配置项,强制 insert -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<!-- 枚举值之间 IDEA 没有对应的配置项,强制 insert -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=Java:SPACE_BEFORE_COMMA-->
<!--org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=Java:SPACE_BEFORE_COMMA
由于 IDEA 只有一个 SPACE_BEFORE_COMMA 选项,所以统一设置 insert_space_before_comma 为 do not insert
-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<!--insert_space_before_comma end-->
<!--org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=Java:SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<!-- IDEA 只有一个配置项 SPACE_AFTER_COMMAinsert_space_after_comma 统一设置成 insert -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<!--insert_space_after_comma end-->
<!--org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=Java:SPACE_BEFORE_COLON-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=Java:SPACE_AFTER_COLON-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<!-- IDEA 不支持配置,默认 do not insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<!-- 这个在 Eclipse 也没有找到配置的地方 -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_semicolon=Java:SPACE_BEFORE_SEMICOLON
程序导入的时候强制将 SPACE_BEFORE_SEMICOLON 设置为 false
-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<!-- SPACE_AFTER_SEMICOLON=true -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<!-- IDEA不支持配置,do not insert -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<!-- IDEA 不支持,使用默认 -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=Java:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
<!-- IDEA不支持配置使用如下值两者对应 -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<!-- Java:SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=Java:SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENT-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=Java:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<!-- IDEA使用了对应的配置Java:SPACE_WITHIN_ARRAY_INITIALIZER_BRACES但感觉不太好IDEA默认不插入Eclipse也使用不插入 -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/>
<!--use default insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<!--use default do not insert -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<!-- use default insert -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=Java:SPACE_BEFORE_SWITCH_LBRACE-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=Java:SPACE_BEFORE_CLASS_LBRACE-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=Java:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=Java:SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=Java:SPACE_BEFORE_METHOD_LBRACE-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=Java:SPACE_AFTER_QUEST-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=Java:SPACE_BEFORE_QUEST-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=Java:SPACE_BEFORE_ANOTATION_PARAMETER_LIST-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<!--use default do not insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<!-- 下面两个对应 IDEA 中的一个配置 Java:SPACE_AROUND_ASSIGNMENT_OPERATORS使用 insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=Java:SPACE_BEFORE_CATCH_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=Java:SPACE_BEFORE_METHOD_CALL_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=Java:SPACE_BEFORE_TRY_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<!-- 下面两个对应 IDEA 中的一个配置 Java:SPACE_AROUND_UNARY_OPERATOR使用 do not insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=Java:SPACE_BEFORE_IF_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=Java:SPACE_BEFORE_WHILE_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=Java:SPACE_AFTER_TYPE_CAST-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=Java:SPACE_BEFORE_METHOD_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=Java:SPACE_BEFORE_FOR_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=Java:SPACE_BEFORE_SYNCHRONIZED_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=Java:SPACE_BEFORE_SWITCH_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
<!--下面两个对应 IDEA 中的一个配置 Java:SPACE_AROUND_LAMBDA_ARROW使用 insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<!-- SPACE_WITHIN_EMPTY_ARRAY_INITIALIZER_BRACES -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<!-- IDEA -> Wrapping And Braces -> Simple classes in one line -->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="do not insert"/>
<!-- IDEA -> Wrapping And Braces -> Simple method in one line -->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/>
<!--因为 IDEA 不支持配置,所以设置为 IDEA 默认值-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="insert"/>
<!-- IDEA 可以通过 Wrap Always 实现-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<!-- IDEA -> Wrapping And Braces -> Simple block in one line -> do not select -->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
<!-- IDEA -> Wrapping And Braces -> try statement -> catch.... (Java:CATCH_ON_NEW_LINE) -->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=Java:ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<!--#org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=Java:ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=Java:ELSE_ON_NEW_LINE-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=Java:WHILE_ON_NEW_LINE-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=Java:FINALLY_ON_NEW_LINE-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<!-- comment start -->
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
<!-- ENABLE_JAVADOC_FORMATTING -->
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<!--org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<!-- IDEA 无对应设置,所以关闭对 block comment 的格式化 -->
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<!--org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=Java:KEEP_FIRST_COLUMN_COMMENT-->
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<!--org.eclipse.jdt.core.formatter.use_on_off_tags=FORMATTER_TAGS_ENABLED-->
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<!--org.eclipse.jdt.core.formatter.disabling_tag=FORMATTER_OFF_TAG-->
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<!--org.eclipse.jdt.core.formatter.enabling_tag=FORMATTER_ON_TAG-->
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<!-- 下面的没有 IDEA 对应项,在代码里面对 IDEA 中使用默认值即可LINE_COMMENT_AT_FIRST_COLUMN BLOCK_COMMENT_AT_FIRST_COLUMN 设置为 false -->
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<!-- 和 IDEA 保持一致,注释换行 -->
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
<!-- comment end -->
<!--org.eclipse.jdt.core.formatter.blank_lines_after_imports=Java:BLANK_LINES_AFTER_IMPORTS-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_before_imports=Java:BLANK_LINES_BEFORE_IMPORTS-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_after_package=Java:BLANK_LINES_AFTER_PACKAGE-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=Java:BLANK_LINES_AROUND_CLASS-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<!--org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=Java:BLANK_LINES_BEFORE_METHOD_BODY-->
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=Java:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_before_field=Java:BLANK_LINES_AROUND_FIELD-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_before_method=Java:BLANK_LINES_AROUND_METHOD-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_before_package=Java:BLANK_LINES_BEFORE_PACKAGE-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<!-- 下面 IDEA 没有对应设置,使用对应值即可 -->
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_preserve"/>
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_preserve"/>
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_preserve"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_preserve"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_preserve"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_preserve"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_preserve"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<!--org.eclipse.jdt.core.formatter.indentation.size=Java:IndentOptions:INDENT_SIZE-->
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<!--org.eclipse.jdt.core.formatter.continuation_indentation=Java:IndentOptions:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="1"/>
<!--org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=Java:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<!--org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=Java:IndentOptions:SMART_TABS-->
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<!--org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=Java:INDENT_CASE_FROM_SWITCH-->
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<!-- KEEP_INDENTS_ON_EMPTY_LINES -->
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<!--org.eclipse.jdt.core.formatter.tabulation.size=Java:IndentOptions:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<!-- Java:IndentOptions:<Programmatic> -->
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<!-- 下面 IDEA 没有对应设置,使用对应值即可 -->
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="82"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="82"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="18"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<!-- Java:<Programmatic> -->
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<!-- 下面没有对应的 IDEA 设置Eclipse 先使用对应值 -->
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="16"/>
<!-- IDEA 默认配置在同一行Eclipse 使用对应值即可-->
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<!-- Java:BINARY_OPERATION_SIGN_ON_NEXT_LINE -->
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
<!-- ASSIGNMENT_WRAP 需要设置为 WRAP_AS_NEEDED WRAP_AS_NEEDED . Add in jdt.core-3.12it's not work in previous version -->
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<!-- IDEA无配置项Eclipse 使用对应值即可 -->
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<!--org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=Java:KEEP_CONTROL_STATEMENT_IN_ONE_LINE-->
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<!--org.eclipse.jdt.core.formatter.compact_else_if=Java:SPECIAL_ELSE_IF_TREATMENT-->
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<!-- Java:ALIGN_GROUP_FIELD_DECLARATIONS -->
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<!-- Java:<Programmatic> -->
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<!-- 统一为 end_of_lintIDEA 默认一致-->
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<!-- <setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
-->
<!-- Java:KEEP_SIMPLE_BLOCKS_IN_ONE_LINE -->
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<!-- Java:CLASS_BRACE_STYLE统一使用end_of_line -->
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<!--org.eclipse.jdt.core.formatter.lineSplit=RIGHT_MARGIN-->
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
</profile>
</profiles>
</profiles>

View File

@@ -0,0 +1,153 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>top.charles7c</groupId>
<artifactId>continew-admin</artifactId>
<version>${revision}</version>
</parent>
<artifactId>continew-admin-common</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>公共模块(存放公共工具类,公共配置等)</description>
<dependencies>
<!-- ################ Spring Boot 相关 ################ -->
<!-- Spring Boot Web提供 Spring MVC Web 开发能力,默认内置 Tomcat 服务器) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 移除内置 Tomcat 服务器 -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Undertow 服务器(采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
<!-- 移除 websocket 依赖,后续使用 websocket 可考虑由 Netty 提供。另可解决日志警告UT026010: Buffer pool was not set on WebSocketDeploymentInfo, the default pool will be used -->
<exclusions>
<exclusion>
<groupId>io.undertow</groupId>
<artifactId>undertow-websockets-jsr</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Java 邮件支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- FreeMarker模板引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<!-- Hibernate Validator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- ################ Sa-Token 相关 ################ -->
<!-- Sa-Token轻量级 Java 权限认证框架,让鉴权变得简单、优雅) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
</dependency>
<!-- Sa-Token 整合 JWT -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
</dependency>
<!-- ################ 持久层相关 ################ -->
<!-- MyBatis PlusMyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,简化开发、提高效率) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- Dynamic Datasource基于 Spring Boot 的快速集成多数据源的启动器) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
<!-- MySQL Java 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- P6SpySQL 性能分析组件) -->
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
</dependency>
<!-- ################ 工具库相关 ################ -->
<!-- SMS4J短信聚合框架轻松集成多家短信服务解决接入多个短信 SDK 的繁琐流程) -->
<dependency>
<groupId>org.dromara.sms4j</groupId>
<artifactId>sms4j-spring-boot-starter</artifactId>
</dependency>
<!-- Just Auth开箱即用的整合第三方登录的开源组件脱离繁琐的第三方登录 SDK让登录变得 So easy! -->
<dependency>
<groupId>com.xkcoding.justauth</groupId>
<artifactId>justauth-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>me.zhyd.oauth</groupId>
<artifactId>JustAuth</artifactId>
</dependency>
<!-- Easy Excel一个基于 Java 的、快速、简洁、解决大文件内存溢出的 Excel 处理工具) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>
<!-- 第三方封装 Ip2region离线 IP 数据管理框架和定位库支持亿级别的数据段10 微秒级别的查询性能,提供了许多主流编程语言的 xdb 数据管理引擎的实现) -->
<dependency>
<groupId>net.dreamlu</groupId>
<artifactId>mica-ip2region</artifactId>
</dependency>
<!-- Knife4j前身是 swagger-bootstrap-ui集 Swagger2 和 OpenAPI3 为一体的增强解决方案) -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
</dependency>
<!-- Redisson不仅仅是一个 Redis Java 客户端) -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-27</artifactId>
</dependency>
<!-- Easy CaptchaJava 图形验证码,支持 gif、中文、算术等类型可用于 Java Web、JavaSE 等项目) -->
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.common.annotation;
import java.lang.annotation.*;
/**
* 增删改查请求映射器注解
*
* @author Charles7c
* @since 2023/1/27 9:54
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrudRequestMapping {
/**
* 路径映射 URI等同于@RequestMapping("/foo1")
*/
String value() default "";
/**
* API 列表
*/
Api[] api() default {Api.PAGE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT};
/**
* API 枚举
*/
enum Api {
/**
* 所有 API
*/
ALL,
/**
* 分页
*/
PAGE,
/**
* 树列表
*/
TREE,
/**
* 列表
*/
LIST,
/**
* 详情
*/
GET,
/**
* 新增
*/
ADD,
/**
* 修改
*/
UPDATE,
/**
* 删除
*/
DELETE,
/**
* 导出
*/
EXPORT,
}
}

View File

@@ -14,26 +14,23 @@
* limitations under the License.
*/
package top.continew.admin.common.config.excel;
package top.charles7c.cnadmin.common.annotation;
import java.lang.annotation.*;
/**
* 字典字段注解
* 数据权限注解
*
* @author Charles7c
* @since 2025/4/9 20:25
* @since 2023/3/6 23:34
*/
@Target(ElementType.FIELD)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DictExcelProperty {
public @interface DataPermission {
/**
* 字典编码
*
* @return 字典编码
* 表别名
*/
String value();
String value() default "";
}

View File

@@ -14,22 +14,39 @@
* limitations under the License.
*/
package top.continew.admin.schedule.annotation;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import top.continew.starter.core.constant.PropertiesConstants;
package top.charles7c.cnadmin.common.annotation;
import java.lang.annotation.*;
import top.charles7c.cnadmin.common.enums.QueryTypeEnum;
/**
* 是否启用 Snail Job 注解
* 查询注解
*
* @author Zheng JieELADMIN
* @author Charles7c
* @since 2025/5/18 12:03
* @since 2023/1/15 18:01
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@ConditionalOnProperty(prefix = "snail-job", name = PropertiesConstants.ENABLED, havingValue = "true", matchIfMissing = true)
public @interface ConditionalOnEnabledScheduleJob {
}
public @interface Query {
/**
* 属性名默认和使用该注解的属性的名称一致
*/
String property() default "";
/**
* 查询类型等值查询模糊查询范围查询等
*/
QueryTypeEnum type() default QueryTypeEnum.EQUAL;
/**
* 多属性模糊查询仅支持 String 类型属性
* <p>
* 例如@Query(blurry = {"username", "email"}) 表示根据用户名和邮箱模糊查询
* </p>
*/
String[] blurry() default {};
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.common.annotation;
import java.lang.annotation.*;
/**
* 树结构字段
*
* @see cn.hutool.core.lang.tree.TreeNodeConfig
* @author Charles7c
* @since 2023/2/26 23:50
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TreeField {
/**
* ID 字段名
*
* @return ID 字段名
*/
String value() default "key";
/**
* 父 ID 字段名
*
* @return 父 ID 字段名
*/
String parentIdKey() default "parentId";
/**
* 名称字段名
*
* @return 名称字段名
*/
String nameKey() default "title";
/**
* 排序字段名
*
* @return 排序字段名
*/
String weightKey() default "sort";
/**
* 子列表字段名
*
* @return 子列表字段名
*/
String childrenKey() default "children";
/**
* 递归深度(< 0 不限制)
*
* @return 递归深度
*/
int deep() default -1;
}

View File

@@ -0,0 +1,216 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.common.base;
import static top.charles7c.cnadmin.common.annotation.CrudRequestMapping.Api;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import lombok.NoArgsConstructor;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil;
import top.charles7c.cnadmin.common.annotation.CrudRequestMapping;
import top.charles7c.cnadmin.common.constant.StringConsts;
import top.charles7c.cnadmin.common.model.query.PageQuery;
import top.charles7c.cnadmin.common.model.query.SortQuery;
import top.charles7c.cnadmin.common.model.resp.PageDataResp;
import top.charles7c.cnadmin.common.model.resp.R;
/**
* 控制器基类
*
* @param <S>
* 业务接口
* @param <L>
* 列表信息
* @param <D>
* 详情信息
* @param <Q>
* 查询条件
* @param <C>
* 创建或修改信息
* @author Charles7c
* @since 2023/1/26 10:45
*/
@NoArgsConstructor
public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, C extends BaseReq> {
@Autowired
protected S baseService;
/**
* 分页查询列表
*
* @param query
* 查询条件
* @param pageQuery
* 分页查询条件
* @return 分页信息
*/
@Operation(summary = "分页查询列表", description = "分页查询列表")
@ResponseBody
@GetMapping
public R<PageDataResp<L>> page(Q query, @Validated PageQuery pageQuery) {
this.checkPermission(Api.LIST);
return R.ok(baseService.page(query, pageQuery));
}
/**
* 查询树列表
*
* @param query
* 查询条件
* @param sortQuery
* 排序查询条件
* @return 树列表信息
*/
@Operation(summary = "查询树列表", description = "查询树列表")
@ResponseBody
@GetMapping("/tree")
public R<List<Tree<Long>>> tree(Q query, SortQuery sortQuery) {
this.checkPermission(Api.LIST);
return R.ok(baseService.tree(query, sortQuery, false));
}
/**
* 查询列表
*
* @param query
* 查询条件
* @param sortQuery
* 排序查询条件
* @return 列表信息
*/
@Operation(summary = "查询列表", description = "查询列表")
@ResponseBody
@GetMapping("/list")
public R<List<L>> list(Q query, SortQuery sortQuery) {
this.checkPermission(Api.LIST);
return R.ok(baseService.list(query, sortQuery));
}
/**
* 查看详情
*
* @param id
* ID
* @return 详情信息
*/
@Operation(summary = "查看详情", description = "查看详情")
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
@ResponseBody
@GetMapping("/{id}")
public R<D> get(@PathVariable Long id) {
this.checkPermission(Api.LIST);
return R.ok(baseService.get(id));
}
/**
* 新增
*
* @param req
* 创建信息
* @return 自增 ID
*/
@Operation(summary = "新增数据", description = "新增数据")
@ResponseBody
@PostMapping
public R<Long> add(@Validated(ValidateGroup.Crud.Add.class) @RequestBody C req) {
this.checkPermission(Api.ADD);
Long id = baseService.add(req);
return R.ok("新增成功", id);
}
/**
* 修改
*
* @param req
* 修改信息
* @param id
* ID
* @return /
*/
@Operation(summary = "修改数据", description = "修改数据")
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
@ResponseBody
@PutMapping("/{id}")
public R update(@Validated(ValidateGroup.Crud.Update.class) @RequestBody C req, @PathVariable Long id) {
this.checkPermission(Api.UPDATE);
baseService.update(req, id);
return R.ok("修改成功");
}
/**
* 删除
*
* @param ids
* ID 列表
* @return /
*/
@Operation(summary = "删除数据", description = "删除数据")
@Parameter(name = "ids", description = "ID 列表", example = "1,2", in = ParameterIn.PATH)
@ResponseBody
@DeleteMapping("/{ids}")
public R delete(@PathVariable List<Long> ids) {
this.checkPermission(Api.DELETE);
baseService.delete(ids);
return R.ok("删除成功");
}
/**
* 导出
*
* @param query
* 查询条件
* @param sortQuery
* 排序查询条件
* @param response
* 响应对象
*/
@Operation(summary = "导出数据", description = "导出数据")
@GetMapping("/export")
public void export(Q query, SortQuery sortQuery, HttpServletResponse response) {
this.checkPermission(Api.EXPORT);
baseService.export(query, sortQuery, response);
}
/**
* 根据 API 类型进行权限验证
*
* @param api
* API 类型
*/
private void checkPermission(Api api) {
CrudRequestMapping crudRequestMapping = this.getClass().getDeclaredAnnotation(CrudRequestMapping.class);
String path = crudRequestMapping.value();
String permissionPrefix = String.join(StringConsts.COLON, StrUtil.splitTrim(path, StringConsts.SLASH));
StpUtil.checkPermission(String.format("%s:%s", permissionPrefix, api.name().toLowerCase()));
}
}

View File

@@ -14,32 +14,34 @@
* limitations under the License.
*/
package top.continew.admin.common.model.entity;
package top.charles7c.cnadmin.common.base;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import top.continew.starter.extension.crud.model.entity.BaseIdDO;
import java.io.Serial;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableId;
/**
* 实体类基类
*
* <p>
* 通用字段ID创建人创建时间修改人修改时间
* </p>
*
* @author Charles7c
* @since 2025/1/12 23:00
* @since 2022/12/12 23:02
*/
@Data
public class BaseDO extends BaseIdDO {
public class BaseDO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId
private Long id;
/**
* 创建人
*/

View File

@@ -14,38 +14,32 @@
* limitations under the License.
*/
package top.continew.admin.common.model.resp;
package top.charles7c.cnadmin.common.base;
import cn.crane4j.annotation.Assemble;
import cn.crane4j.annotation.Mapping;
import cn.crane4j.annotation.condition.ConditionOnPropertyNotNull;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.continew.admin.common.constant.ContainerConstants;
import java.io.Serial;
import java.time.LocalDateTime;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* 详情响应参数基类
* 详情响应基类
*
* @author Charles7c
* @since 2024/12/27 20:32
* @since 2023/1/26 10:40
*/
@Data
public class BaseDetailResp extends BaseResp {
@Serial
private static final long serialVersionUID = 1L;
/**
* 修改人
*/
@JsonIgnore
@ConditionOnPropertyNotNull
@Assemble(container = ContainerConstants.USER_NICKNAME, props = @Mapping(ref = "updateUserString"))
private Long updateUser;
/**

View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.common.base;
import java.util.Collection;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import cn.hutool.core.util.ClassUtil;
/**
* Mapper 基类
*
* @param <T>
* 实体类
* @author Charles7c
* @since 2023/2/19 20:47
*/
public interface BaseMapper<T> extends com.baomidou.mybatisplus.core.mapper.BaseMapper<T> {
/**
* 批量插入记录
*
* @param entityList
* 实体列表
* @return 是否成功
*/
default boolean insertBatch(Collection<T> entityList) {
return Db.saveBatch(entityList);
}
/**
* 批量更新记录
*
* @param entityList
* 实体列表
* @return 是否成功
*/
default boolean updateBatchById(Collection<T> entityList) {
return Db.updateBatchById(entityList);
}
/**
* 链式查询
*
* @return QueryWrapper 的包装类
*/
default QueryChainWrapper<T> query() {
return ChainWrappers.queryChain(this);
}
/**
* 链式查询lambda 式)
*
* @return LambdaQueryWrapper 的包装类
*/
default LambdaQueryChainWrapper<T> lambdaQuery() {
return ChainWrappers.lambdaQueryChain(this, this.currentEntityClass());
}
/**
* 链式查询lambda 式)
*
* @param entity
* 实体对象
* @return LambdaQueryWrapper 的包装类
*/
default LambdaQueryChainWrapper<T> lambdaQuery(T entity) {
return ChainWrappers.lambdaQueryChain(this, entity);
}
/**
* 链式更改
*
* @return UpdateWrapper 的包装类
*/
default UpdateChainWrapper<T> update() {
return ChainWrappers.updateChain(this);
}
/**
* 链式更改lambda 式)
*
* @return LambdaUpdateWrapper 的包装类
*/
default LambdaUpdateChainWrapper<T> lambdaUpdate() {
return ChainWrappers.lambdaUpdateChain(this);
}
/**
* 获取实体类 Class 对象
*
* @return 实体类 Class 对象
*/
default Class<T> currentEntityClass() {
return (Class<T>)ClassUtil.getTypeArgument(this.getClass(), 0);
}
}

View File

@@ -14,16 +14,20 @@
* limitations under the License.
*/
package top.continew.admin.system.mapper;
package top.charles7c.cnadmin.common.base;
import top.continew.admin.system.model.entity.StorageDO;
import top.continew.starter.data.mp.base.BaseMapper;
import java.io.Serializable;
import lombok.Data;
/**
* 存储 Mapper
* 请求基类
*
* @author Charles7c
* @since 2023/12/26 22:09
* @since 2023/1/30 21:51
*/
public interface StorageMapper extends BaseMapper<StorageDO> {
}
@Data
public class BaseReq implements Serializable {
private static final long serialVersionUID = 1L;
}

View File

@@ -14,31 +14,28 @@
* limitations under the License.
*/
package top.continew.admin.common.model.resp;
package top.charles7c.cnadmin.common.base;
import cn.crane4j.annotation.Assemble;
import cn.crane4j.annotation.Mapping;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.continew.admin.common.constant.ContainerConstants;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
/**
* 响应参数基类
* 响应基类
*
* @author Charles7c
* @since 2024/12/27 20:32
* @since 2023/1/26 10:40
*/
@Data
public class BaseResp implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
@@ -52,7 +49,6 @@ public class BaseResp implements Serializable {
* 创建人
*/
@JsonIgnore
@Assemble(container = ContainerConstants.USER_NICKNAME, props = @Mapping(ref = "createUserString"))
private Long createUser;
/**

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.common.base;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import cn.hutool.core.lang.tree.Tree;
import top.charles7c.cnadmin.common.model.query.PageQuery;
import top.charles7c.cnadmin.common.model.query.SortQuery;
import top.charles7c.cnadmin.common.model.resp.PageDataResp;
/**
* 业务接口基类
*
* @param <L>
* 列表信息
* @param <D>
* 详情信息
* @param <Q>
* 查询条件
* @param <C>
* 创建或修改信息
* @author Charles7c
* @since 2023/1/26 16:54
*/
public interface BaseService<L, D, Q, C extends BaseReq> {
/**
* 分页查询列表
*
* @param query
* 查询条件
* @param pageQuery
* 分页查询条件
* @return 分页列表信息
*/
PageDataResp<L> page(Q query, PageQuery pageQuery);
/**
* 查询树列表
*
* @param query
* 查询条件
* @param sortQuery
* 排序查询条件
* @param isSimple
* 是否为简单树结构(不包含基本树结构之外的扩展字段)
* @return 树列表信息
*/
List<Tree<Long>> tree(Q query, SortQuery sortQuery, boolean isSimple);
/**
* 查询列表
*
* @param query
* 查询条件
* @param sortQuery
* 排序查询条件
* @return 列表信息
*/
List<L> list(Q query, SortQuery sortQuery);
/**
* 查看详情
*
* @param id
* ID
* @return 详情信息
*/
D get(Long id);
/**
* 新增
*
* @param req
* 创建信息
* @return 自增 ID
*/
Long add(C req);
/**
* 修改
*
* @param req
* 修改信息
* @param id
* ID
*/
void update(C req, Long id);
/**
* 删除
*
* @param ids
* ID 列表
*/
void delete(List<Long> ids);
/**
* 导出
*
* @param query
* 查询条件
* @param sortQuery
* 排序查询条件
* @param response
* 响应对象
*/
void export(Q query, SortQuery sortQuery, HttpServletResponse response);
}

View File

@@ -0,0 +1,264 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.common.base;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import top.charles7c.cnadmin.common.annotation.TreeField;
import top.charles7c.cnadmin.common.model.query.PageQuery;
import top.charles7c.cnadmin.common.model.query.SortQuery;
import top.charles7c.cnadmin.common.model.resp.PageDataResp;
import top.charles7c.cnadmin.common.service.CommonUserService;
import top.charles7c.cnadmin.common.util.ExcelUtils;
import top.charles7c.cnadmin.common.util.ExceptionUtils;
import top.charles7c.cnadmin.common.util.ReflectUtils;
import top.charles7c.cnadmin.common.util.TreeUtils;
import top.charles7c.cnadmin.common.util.helper.QueryHelper;
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
/**
* 业务实现基类
*
* @param <M>
* Mapper 接口
* @param <T>
* 实体类
* @param <L>
* 列表信息
* @param <D>
* 详情信息
* @param <Q>
* 查询条件
* @param <C>
* 创建或修改信息
* @author Charles7c
* @since 2023/1/26 21:52
*/
public abstract class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseDO, L, D, Q, C extends BaseReq>
implements BaseService<L, D, Q, C> {
@Autowired
protected M baseMapper;
private final Class<T> entityClass;
private final Class<L> listClass;
private final Class<D> detailClass;
protected BaseServiceImpl() {
this.entityClass = (Class<T>)ClassUtil.getTypeArgument(this.getClass(), 1);
this.listClass = (Class<L>)ClassUtil.getTypeArgument(this.getClass(), 2);
this.detailClass = (Class<D>)ClassUtil.getTypeArgument(this.getClass(), 3);
}
@Override
public PageDataResp<L> page(Q query, PageQuery pageQuery) {
QueryWrapper<T> queryWrapper = QueryHelper.build(query);
IPage<T> page = baseMapper.selectPage(pageQuery.toPage(), queryWrapper);
PageDataResp<L> pageDataResp = PageDataResp.build(page, listClass);
pageDataResp.getList().forEach(this::fill);
return pageDataResp;
}
@Override
public List<Tree<Long>> tree(Q query, SortQuery sortQuery, boolean isSimple) {
List<L> list = this.list(query, sortQuery);
if (CollUtil.isEmpty(list)) {
return new ArrayList<>(0);
}
// 如果构建简单树结构,则不包含基本树结构之外的扩展字段
TreeNodeConfig treeNodeConfig = TreeUtils.DEFAULT_CONFIG;
TreeField treeField = listClass.getDeclaredAnnotation(TreeField.class);
if (!isSimple) {
// 根据 @TreeField 配置生成树结构配置
treeNodeConfig = TreeUtils.genTreeNodeConfig(treeField);
}
// 构建树
return TreeUtils.build(list, treeNodeConfig, (node, tree) -> {
// 转换器
tree.setId(ReflectUtil.invoke(node, StrUtil.genGetter(treeField.value())));
tree.setParentId(ReflectUtil.invoke(node, StrUtil.genGetter(treeField.parentIdKey())));
tree.setName(ReflectUtil.invoke(node, StrUtil.genGetter(treeField.nameKey())));
tree.setWeight(ReflectUtil.invoke(node, StrUtil.genGetter(treeField.weightKey())));
if (!isSimple) {
List<Field> fieldList = ReflectUtils.getNonStaticFields(listClass);
fieldList.removeIf(f -> StrUtil.containsAnyIgnoreCase(f.getName(), treeField.value(),
treeField.parentIdKey(), treeField.nameKey(), treeField.weightKey(), treeField.childrenKey()));
fieldList
.forEach(f -> tree.putExtra(f.getName(), ReflectUtil.invoke(node, StrUtil.genGetter(f.getName()))));
}
});
}
@Override
public List<L> list(Q query, SortQuery sortQuery) {
List<L> list = this.list(query, sortQuery, listClass);
list.forEach(this::fill);
return list;
}
/**
* 查询列表
*
* @param query
* 查询条件
* @param sortQuery
* 排序查询条件
* @param targetClass
* 指定类型
* @return 列表信息
*/
protected <E> List<E> list(Q query, SortQuery sortQuery, Class<E> targetClass) {
QueryWrapper<T> queryWrapper = QueryHelper.build(query);
// 设置排序
this.sort(queryWrapper, sortQuery);
List<T> entityList = baseMapper.selectList(queryWrapper);
return BeanUtil.copyToList(entityList, targetClass);
}
/**
* 设置排序
*
* @param queryWrapper
* 查询 Wrapper
* @param sortQuery
* 排序查询条件
*/
protected void sort(QueryWrapper<T> queryWrapper, SortQuery sortQuery) {
Sort sort = Opt.ofNullable(sortQuery).orElseGet(SortQuery::new).getSort();
for (Sort.Order order : sort) {
if (null != order) {
queryWrapper.orderBy(true, order.isAscending(), StrUtil.toUnderlineCase(order.getProperty()));
}
}
}
@Override
public D get(Long id) {
T entity = this.getById(id);
D detail = BeanUtil.copyProperties(entity, detailClass);
this.fillDetail(detail);
return detail;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Long add(C req) {
if (null == req) {
return 0L;
}
T entity = BeanUtil.copyProperties(req, entityClass);
baseMapper.insert(entity);
return entity.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void update(C req, Long id) {
T entity = this.getById(id);
BeanUtil.copyProperties(req, entity, CopyOptions.create().ignoreNullValue());
baseMapper.updateById(entity);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(List<Long> ids) {
baseMapper.deleteBatchIds(ids);
}
@Override
public void export(Q query, SortQuery sortQuery, HttpServletResponse response) {
List<D> list = this.list(query, sortQuery, detailClass);
list.forEach(this::fillDetail);
ExcelUtils.export(list, "导出数据", detailClass, response);
}
/**
* 根据 ID 查询
*
* @param id
* ID
* @return 实体信息
*/
protected T getById(Object id) {
T entity = baseMapper.selectById(Convert.toStr(id));
CheckUtils.throwIfNotExists(entity, ClassUtil.getClassName(entityClass, true), "ID", id);
return entity;
}
/**
* 填充数据
*
* @param baseObj
* 待填充列表信息
*/
protected void fill(Object baseObj) {
if (baseObj instanceof BaseResp) {
BaseResp baseResp = (BaseResp)baseObj;
Long createUser = baseResp.getCreateUser();
if (null == createUser) {
return;
}
CommonUserService userService = SpringUtil.getBean(CommonUserService.class);
baseResp.setCreateUserString(ExceptionUtils.exToNull(() -> userService.getNicknameById(createUser)));
}
}
/**
* 填充详情数据
*
* @param detailObj
* 待填充详情信息
*/
public void fillDetail(Object detailObj) {
if (detailObj instanceof BaseDetailResp) {
BaseDetailResp detail = (BaseDetailResp)detailObj;
this.fill(detail);
Long updateUser = detail.getUpdateUser();
if (null == updateUser) {
return;
}
CommonUserService userService = SpringUtil.getBean(CommonUserService.class);
detail.setUpdateUserString(ExceptionUtils.exToNull(() -> userService.getNicknameById(updateUser)));
}
}
}

View File

@@ -14,55 +14,33 @@
* limitations under the License.
*/
package top.continew.admin.common.config.mybatis;
package top.charles7c.cnadmin.common.base;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import top.continew.starter.data.mp.base.BaseMapper;
import top.continew.starter.extension.datapermission.annotation.DataPermission;
import java.util.List;
import top.charles7c.cnadmin.common.annotation.DataPermission;
/**
* 数据权限 Mapper 基类
*
* @param <T> 实体类
* @param <T>
* 实体类
* @author Charles7c
* @since 2023/9/3 21:50
*/
public interface DataPermissionMapper<T> extends BaseMapper<T> {
/**
* 根据 entity 条件查询全部记录
*
* @param queryWrapper 实体对象封装操作类可以为 null
* @return 全部记录
*/
@DataPermission
@Override
@DataPermission
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件查询全部记录并翻页
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类可以为 null
* @return 全部记录并翻页
*/
@DataPermission
@Override
@DataPermission
List<T> selectList(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 ID 删除
*
* @param obj 主键ID或实体
* @param useFill 是否填充
* @return 删除个数
*/
@DataPermission
@Override
int deleteById(Object obj, boolean useFill);
}

Some files were not shown because too many files have changed in this diff Show More