初始提交

main
刘政 3 weeks ago
parent 44f7a0f869
commit 727202d135

@ -0,0 +1,19 @@
root = true
[*]
end_of_line = lf
charset = utf-8
indent_style = space
indent_size = 4
[*.yml]
indent_style = space
indent_size = 2
[*.vue.ftl]
indent_style = space
indent_size = 2
[*.ts.ftl]
indent_style = space
indent_size = 2

6
.gitattributes vendored

@ -0,0 +1,6 @@
# 默认所有文件作为文本处理,统一换行符为 LF
* text eol=lf
# 针对二进制文件禁止换行符转换
*.png binary
*.xdb binary

@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

@ -0,0 +1,13 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "maven" # See documentation for possible values
directory: "/sz-dependencies" # Location of package manifests
schedule:
interval: "weekly"
target-branch: dev # 指定要检查的目标分支
open-pull-requests-limit: 20 # 限制同时打开的PR数量

@ -0,0 +1,130 @@
name: Docker Sz Services CI
on:
push:
branches: [ "preview" ]
pull_request:
branches: [ "preview" ]
workflow_dispatch:
jobs:
build-and-deploy:
name: Build & Deploy ${{ matrix.app_name }}
runs-on: ubuntu-latest
strategy:
max-parallel: 1 # 串行处理多个服务,保证部署顺序
matrix:
include:
- app_name: sz-service-admin
service_port: 9991
log_dir: /home/app/sz-service-admin/logs
config_dir: /home/conf/sz-service-admin
jar_dir: ./sz-service/sz-service-admin/target
docker_compose_path: /home/docker-compose/sz-service-admin
- app_name: sz-service-websocket
service_port: 9993
log_dir: /home/app/sz-service-websocket/logs
config_dir: /home/conf/sz-service-websocket
jar_dir: ./sz-service/sz-service-websocket/target
docker_compose_path: /home/docker-compose/sz-service-websocket
env:
# 镜像仓库相关配置
ACR_DOMAIN: registry.cn-beijing.aliyuncs.com
ACR_ZONE: sz-action
VERSION: latest
# 应用环境配置
RUNNING_ACTIVE: preview
# 容器启动脚本目录(如果直接 docker 启动需要)
SHELL_RUN_DIR: /home/run
steps:
# 1. 拉取源码
- name: Checkout code
uses: actions/checkout@v4
# 2. 安装 JDK 21 环境
- name: Set up JDK 21 (Zulu)
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '21'
cache: 'maven'
# 3. 安装 Maven 工具
- name: Set up Maven 3.8.2
uses: stCarolas/setup-maven@v5
with:
maven-version: 3.8.2
# 4. Maven 编译打包
- name: Build with Maven
run: mvn clean package
# 5. 复制打包产物 JAR 文件到工作目录(方便 Docker 构建)
- name: Copy JAR file to workspace
run: |
cd ${{ matrix.jar_dir }}
cp ./*.jar ../../../app.jar
# 6. 构建 Docker 镜像
- name: Build Docker image
run: docker build -t ${{ matrix.app_name }}:${{ env.VERSION }} .
# 7. 登录阿里云 ACR 仓库
- name: Login to ACR
run: echo "${{ secrets.ACR_PASSWORD }}" | docker login --username=${{ secrets.ACR_USERNAME }} ${{ env.ACR_DOMAIN }} --password-stdin
# 8. 镜像打标签(仓库命名规范)
- name: Tag Docker image
run: docker tag ${{ matrix.app_name }}:${{ env.VERSION }} ${{ env.ACR_DOMAIN }}/${{ env.ACR_ZONE }}/${{ matrix.app_name }}:${{ env.VERSION }}
# 9. 推送镜像到远程仓库
- name: Push Docker image to ACR
run: docker push ${{ env.ACR_DOMAIN }}/${{ env.ACR_ZONE }}/${{ matrix.app_name }}:${{ env.VERSION }}
# 10. 使用 docker-compose 在远程服务器自动部署(推荐,结合 sz-deploy-v3 脚本)
- name: Deploy with docker-compose on remote server
uses: appleboy/ssh-action@v1.2.0
with:
host: ${{ secrets.REMOTE_HOST }}
username: ${{ secrets.REMOTE_USER }}
password: ${{ secrets.REMOTE_PASSWORD }}
script: |
cd ${{ matrix.docker_compose_path }}
bash upgrade.sh
# ————— 以下流程为可选直接 docker 启动,建议使用上方 docker-compose 部署,如需手动容器管理可启用—————
# - name: Direct Docker deploy on remote server
# uses: appleboy/ssh-action@v1.2.0
# with:
# host: ${{ secrets.REMOTE_HOST }}
# username: ${{ secrets.REMOTE_USER }}
# password: ${{ secrets.REMOTE_PASSWORD }}
# script: |
# docker pull ${{ env.ACR_DOMAIN }}/${{ env.ACR_ZONE }}/${{ matrix.app_name }}:${{ env.VERSION }}
# echo "=== 生成容器启动脚本 ==="
# mkdir -p ${{ env.SHELL_RUN_DIR }}
# START_SCRIPT="${{ env.SHELL_RUN_DIR }}/docker_run_${{ matrix.app_name }}_${{ env.RUNNING_ACTIVE }}.sh"
# cat > $START_SCRIPT <<EOL
# #!/bin/bash
# echo "=== 停止旧容器 ==="
# docker stop ${{ matrix.app_name }} || true
# docker rm ${{ matrix.app_name }} || true
# docker image prune -f
# docker builder prune -f
# echo "=== 启动新容器 ==="
# docker run -itd \\
# --name ${{ matrix.app_name }} \\
# --restart always \\
# -p ${{ matrix.service_port }}:${{ matrix.service_port }} \\
# -v ${{ matrix.log_dir }}:/logs \\
# -v ${{ matrix.config_dir }}:/config \\
# -e "SPRING_PROFILES_ACTIVE=${{ env.RUNNING_ACTIVE }}" \\
# ${{ env.ACR_DOMAIN }}/${{ env.ACR_ZONE }}/${{ matrix.app_name }}:${{ env.VERSION }}
# EOL
# chmod +x $START_SCRIPT
# echo "启动脚本已生成:$START_SCRIPT"
# echo "可执行该脚本手动启动容器:"
# echo "bash $START_SCRIPT"
# bash $START_SCRIPT

@ -0,0 +1,103 @@
name: Docker Sz Services Test CI
on:
push:
branches: [ "test" ]
pull_request:
branches: [ "test" ]
workflow_dispatch:
jobs:
build-and-deploy:
name: Build & Deploy ${{ matrix.app_name }}
runs-on: ubuntu-latest
strategy:
max-parallel: 1 # 串行执行
matrix:
include:
- app_name: sz-service-admin
service_port: 9991
log_dir: /home/app/sz-service-admin/logs
config_dir: /home/conf/sz-service-admin
jar_dir: ./sz-service/sz-service-admin/target
- app_name: sz-service-websocket
service_port: 9993
log_dir: /home/app/sz-service-websocket/logs
config_dir: /home/conf/sz-service-websocket
jar_dir: ./sz-service/sz-service-websocket/target
env:
ACR_DOMAIN: registry.cn-beijing.aliyuncs.com
ACR_ZONE: sz-action
VERSION: test
RUNNING_ACTIVE: preview
SHELL_RUN_DIR: /home/run
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '21'
cache: 'maven'
- name: Set up Maven
uses: stCarolas/setup-maven@v5
with:
maven-version: 3.8.2
- name: Build with Maven
run: mvn clean package
- name: Copy JAR file
run: |
cd ${{ matrix.jar_dir }}
cp ./*.jar ../../../app.jar
- name: Build Docker image
run: docker build -t ${{ matrix.app_name }}:${{ env.VERSION }} .
- name: Log in to Docker ACR
run: echo "${{ secrets.ACR_PASSWORD }}" | docker login --username=${{ secrets.ACR_USERNAME }} ${{ env.ACR_DOMAIN }} --password-stdin
- name: Tag Docker image
run: docker tag ${{ matrix.app_name }}:${{ env.VERSION }} ${{ env.ACR_DOMAIN }}/${{ env.ACR_ZONE }}/${{ matrix.app_name }}:${{ env.VERSION }}
- name: Push Docker image
run: docker push ${{ env.ACR_DOMAIN }}/${{ env.ACR_ZONE }}/${{ matrix.app_name }}:${{ env.VERSION }}
- name: Deploy to remote server
uses: appleboy/ssh-action@v1.2.0
with:
host: ${{ secrets.REMOTE_HOST_TEST }}
username: ${{ secrets.REMOTE_USER_TEST }}
password: ${{ secrets.REMOTE_PASSWORD_TEST }}
script: |
docker pull ${{ env.ACR_DOMAIN }}/${{ env.ACR_ZONE }}/${{ matrix.app_name }}:${{ env.VERSION }}
echo "==================== 生成启动命令脚本 ===================="
mkdir -p ${{ env.SHELL_RUN_DIR }}
START_SCRIPT="${{ env.SHELL_RUN_DIR }}/docker_run_${{ matrix.app_name }}_${{ env.RUNNING_ACTIVE }}.sh"
cat > $START_SCRIPT <<EOL
#!/bin/bash
echo "==================== 停止旧应用容器 ===================="
docker stop ${{ matrix.app_name }} || true
docker rm ${{ matrix.app_name }} || true
docker image prune -f
docker builder prune -f
echo "==================== 启动应用容器 ===================="
docker run -itd \\
--name ${{ matrix.app_name }} \\
--restart always \\
-p ${{ matrix.service_port }}:${{ matrix.service_port }} \\
-v ${{ matrix.log_dir }}:/logs \\
-v ${{ matrix.config_dir }}:/config \\
-e "SPRING_PROFILES_ACTIVE=${{ env.RUNNING_ACTIVE }}" \\
${{ env.ACR_DOMAIN }}/${{ env.ACR_ZONE }}/${{ matrix.app_name }}:${{ env.VERSION }}
EOL
chmod +x $START_SCRIPT
echo "启动脚本已生成:$START_SCRIPT"
echo "可以运行以下命令手动启动容器:"
echo "bash $START_SCRIPT"
bash $START_SCRIPT

5
.gitignore vendored

@ -0,0 +1,5 @@
/.idea/
# 忽略所有target文件夹
/**/target/
# 排除logs日志文件夹
/logs/

File diff suppressed because it is too large Load Diff

@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
feiyuchuixue@163.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

@ -0,0 +1,17 @@
FROM azul/zulu-openjdk:21-latest
LABEL authors="sz"
COPY *.jar app.jar
# 安装 curl, 用于蓝绿部署的容器健康检查等,并创建配置和日志目录
RUN set -eux; \
apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/* && \
mkdir -p /config /logs
ARG SPRING_PROFILES_ACTIVE
# 声明挂载点(配置/日志)
VOLUME ["/config", "/logs"]
ENTRYPOINT ["java", "-jar", "-Duser.timezone=Asia/Shanghai","-Dfile.encoding=UTF-8", "app.jar", "--spring.profiles.active=${SPRING_PROFILES_ACTIVE}"]

@ -0,0 +1,2 @@
# api 文档地址
http://127.0.0.1:9991/api/admin/doc.html#

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [2024] [升职哦sz]
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.

@ -0,0 +1,697 @@
# 第三方库和许可证
本项目中引用了以下第三方开源项目及其许可证信息:
## 项目列表
### **[Geeker-Admin](https://github.com/HalseySpicy/Geeker-Admin)**
- **仓库地址**: https://github.com/HalseySpicy/Geeker-Admin
- **许可证类型**: MIT License
- **许可证内容:**
```
MIT License
Copyright (c) 2022 Halsey
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
### [Sa-Token](https://github.com/dromara/Sa-Token)
- **仓库地址**: https://github.com/dromara/Sa-Token
- **许可证类型**: Apache License 2.0
- **许可证内容:**
```
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2011-2019 hubin.
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
https://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.
```
### **[mybatis-flex](https://github.com/mybatis-flex/mybatis-flex)**
- **仓库地址**: https://github.com/mybatis-flex/mybatis-flex
- **许可证类型**: Apache License 2.0
- **许可证内容:**
```
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
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.
```
### [knife4j](https://github.com/xiaoymin/knife4j)
- **仓库地址**: https://github.com/xiaoymin/knife4j
- **许可证类型**: Apache License 2.0
- **许可证内容:**
```
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "{}" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright 2017 小明
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.
```
### [fastexcel](https://github.com/fast-excel/fastexcel)
- **仓库地址**: https://github.com/fast-excel/fastexcel
- **许可证类型**: MIT License
- **许可证内容:**
```
MIT License
Copyright (c) 2024 CodePhiliaX
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## 其他
请确保您遵循每个项目的许可证要求,并在必要时进行相应的说明和归属。

@ -0,0 +1,30 @@
# swagger文档配置
knife4j:
enable: false
setting:
language: zh_cn
springdoc:
default-flat-param-object: true
swagger-ui:
# 是否开启swagger-ui【生产环境】建议关闭
enabled: true
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha·
api-docs:
# 是否开启api-docs【生产环境】建议关闭
enabled: true
path: /v3/api-docs
group-configs:
- group: 'admin'
paths-to-match: '/**'
packages-to-scan: com.sz.admin
- group: 'generator工具'
paths-to-match: '/**'
packages-to-scan: com.sz.generator
- group: 'www网站'
paths-to-match: '/**'
packages-to-scan: com.sz.www
- group: '微信小程序'
paths-to-match: '/**'
packages-to-scan: com.sz.applet

@ -0,0 +1,11 @@
mybatis-flex:
configuration:
map-underscore-to-camel-case: true
jdbc-type-for-null: null
auto-mapping-behavior: full
auto-mapping-unknown-column-behavior: none
cache-enabled: false
global-config:
deleted-value-of-logic-delete: "T"
normal-value-of-logic-delete: "F"

@ -0,0 +1,28 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/sz_admin_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: Yanfa2023@
hikari:
#连接池名
pool-name: HikariCP
#最小空闲连接数
minimum-idle: 5
# 空闲连接存活最大时间默认10分钟
idle-timeout: 600000
# 连接池最大连接数默认是10
maximum-pool-size: 10
# 此属性控制从池返回的连接的默认自动提交行为,默认值true
auto-commit: true
# 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟
max-lifetime: 1800000
# 数据库连接超时时间,默认30秒
connection-timeout: 30000
# 连接测试query
connection-test-query: SELECT 1
liquibase:
change-log: classpath:db/changelog/changelog-master.xml
enabled: true
database-change-log-lock-table: databasechangeloglock
database-change-log-table: databasechangelog

@ -0,0 +1,12 @@
oss:
# 支持S3协议的厂商
provider: MINIO
endpoint: 192.168.56.101:9000
accessKey: a4jtJvgEmk4ead5dzac6
secretKey: UW6kxTGRetIAahV759rFkgoQ8ilXLRUMW0ULdIoo
bucketName: test
richtextBucketName: static
domain: http://192.168.56.101:9000
# 命名方式: UUID、ORIGINAL原文件名偏好冲突会补充时间
naming: original
scheme: https

@ -0,0 +1,5 @@
page-helper:
helperDialect: mysql
reasonable: false
supportMethodsArguments: true
params: count=countSql

@ -0,0 +1,28 @@
# redis
spring:
data:
redis:
#单机配置
host: 127.0.0.1
port: 6379
# 数据索引
database: 0
# 连接超时时间(毫秒)
timeout: 50000
###连接池配置###
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 100
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 30
# 连接池中的最小空闲连接
min-idle: 10
password: 123456
# 开启redis监听
redis:
listener:
enable: true

@ -0,0 +1,44 @@
# sa-token
sa-token:
# token名称 (同时也是cookie名称)
token-name: Authorization
# 是否开启自动续签
auto-renew: true
# token固定超时 设为七天 (必定过期) 单位: 秒
timeout: 604800
# 多端不同 token 有效期 可查看 LoginHelper.loginByDevice 方法自定义
# token最低活跃时间 (指定时间无操作就过期) 单位: 秒
active-timeout: 86400
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: true
# jwt秘钥
jwt-secret-key: abcdefghijklmnopqrstuvwxyz
# 允许动态设置 token 有效期
dynamic-active-timeout: true
# 允许从 请求参数 读取 token
is-read-body: false
# 允许从 header 读取 token
is-read-header: true
# 关闭 cookie 鉴权 从根源杜绝 csrf 漏洞风险
is-read-cookie: false
# token前缀
token-prefix: "Bearer"
# 同一账号最大登录数量,-1代表不限
max-login-count: -1
# 接口白名单
router:
whitelist:
- "/v3/api-docs/**"
- "/doc.html"
- "/webjars/**"
- "/swagger-resources"
- "/favicon.ico"
- "/swagger-ui.html"
- "/www/**"
- "/wechat/**"

@ -0,0 +1,6 @@
edgeBox:
connectTimeout: 8
readTimeout: 10
maxIdleConnections: 16
keepAliveDuration: 5

@ -0,0 +1,30 @@
# swagger文档配置
knife4j:
enable: false
setting:
language: zh_cn
springdoc:
default-flat-param-object: true
swagger-ui:
# 是否开启swagger-ui【生产环境】建议关闭
enabled: true
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha·
api-docs:
# 是否开启api-docs【生产环境】建议关闭
enabled: true
path: /v3/api-docs
group-configs:
- group: 'admin'
paths-to-match: '/**'
packages-to-scan: com.sz.admin
- group: 'generator工具'
paths-to-match: '/**'
packages-to-scan: com.sz.generator
- group: 'www网站'
paths-to-match: '/**'
packages-to-scan: com.sz.www
- group: '微信小程序'
paths-to-match: '/**'
packages-to-scan: com.sz.applet

@ -0,0 +1,11 @@
mybatis-flex:
configuration:
map-underscore-to-camel-case: true
jdbc-type-for-null: null
auto-mapping-behavior: full
auto-mapping-unknown-column-behavior: none
cache-enabled: false
global-config:
deleted-value-of-logic-delete: "T"
normal-value-of-logic-delete: "F"

@ -0,0 +1,28 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/sz_admin_preview?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123456
hikari:
#连接池名
pool-name: HikariCP
#最小空闲连接数
minimum-idle: 5
# 空闲连接存活最大时间默认10分钟
idle-timeout: 600000
# 连接池最大连接数默认是10
maximum-pool-size: 10
# 此属性控制从池返回的连接的默认自动提交行为,默认值true
auto-commit: true
# 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟
max-lifetime: 1800000
# 数据库连接超时时间,默认30秒
connection-timeout: 30000
# 连接测试query
connection-test-query: SELECT 1
liquibase:
change-log: classpath:db/changelog/changelog-master.xml
enabled: true
database-change-log-lock-table: databasechangeloglock
database-change-log-table: databasechangelog

@ -0,0 +1,14 @@
oss:
# 支持S3协议的厂商
provider: MINIO
endpoint: 192.168.56.101:9000
accessKey: a4jtJvgEmk4ead5dzac6
secretKey: UW6kxTGRetIAahV759rFkgoQ8ilXLRUMW0ULdIoo
# 全局存储桶,偏私有存储
bucketName: test
domain: http://192.168.56.101:9000
# 富文本专用存储桶,偏公用存储
richtextBucketName: static
# 命名方式: UUID、ORIGINAL原文件名偏好冲突会补充时间
naming: original
scheme: http

@ -0,0 +1,5 @@
page-helper:
helperDialect: mysql
reasonable: false
supportMethodsArguments: true
params: count=countSql

@ -0,0 +1,28 @@
# redis
spring:
data:
redis:
#单机配置
host: 127.0.0.1
port: 6379
# 数据索引
database: 0
# 连接超时时间(毫秒)
timeout: 50000
###连接池配置###
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 100
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 30
# 连接池中的最小空闲连接
min-idle: 10
password: 123456
# 开启redis监听
redis:
listener:
enable: true

@ -0,0 +1,44 @@
# sa-token
sa-token:
# token名称 (同时也是cookie名称)
token-name: Authorization
# 是否开启自动续签
auto-renew: true
# token固定超时 设为七天 (必定过期) 单位: 秒
timeout: 604800
# 多端不同 token 有效期 可查看 LoginHelper.loginByDevice 方法自定义
# token最低活跃时间 (指定时间无操作就过期) 单位: 秒
active-timeout: 86400
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: true
# jwt秘钥
jwt-secret-key: abcdefghijklmnopqrstuvwxyz
# 允许动态设置 token 有效期
dynamic-active-timeout: true
# 允许从 请求参数 读取 token
is-read-body: false
# 允许从 header 读取 token
is-read-header: true
# 关闭 cookie 鉴权 从根源杜绝 csrf 漏洞风险
is-read-cookie: false
# token前缀
token-prefix: "Bearer"
# 同一账号最大登录数量,-1代表不限
max-login-count: -1
# 接口白名单
router:
whitelist:
- "/v3/api-docs/**"
- "/doc.html"
- "/webjars/**"
- "/swagger-resources"
- "/favicon.ico"
- "/swagger-ui.html"
- "/www/**"
- "/wechat/**"

@ -0,0 +1,10 @@
ZLMediaKit:
ip: 192.168.2.128
port: 8080
app: live
vhost: __defaultVhost__
secret: liuzheng
connectTimeout: 8
readTimeout: 10
maxIdleConnections: 16
keepAliveDuration: 5

@ -0,0 +1,30 @@
# swagger文档配置
knife4j:
enable: false
setting:
language: zh_cn
springdoc:
default-flat-param-object: true
swagger-ui:
# 是否开启swagger-ui【生产环境】建议关闭
enabled: true
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha·
api-docs:
# 是否开启api-docs【生产环境】建议关闭
enabled: true
path: /v3/api-docs
group-configs:
- group: 'admin'
paths-to-match: '/**'
packages-to-scan: com.sz.admin
- group: 'generator工具'
paths-to-match: '/**'
packages-to-scan: com.sz.generator
- group: 'www网站'
paths-to-match: '/**'
packages-to-scan: com.sz.www
- group: '微信小程序'
paths-to-match: '/**'
packages-to-scan: com.sz.applet

@ -0,0 +1,10 @@
mybatis-flex:
configuration:
map-underscore-to-camel-case: true
jdbc-type-for-null: null
auto-mapping-behavior: full
auto-mapping-unknown-column-behavior: none
cache-enabled: false
global-config:
deleted-value-of-logic-delete: "T"
normal-value-of-logic-delete: "F"

@ -0,0 +1,28 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/sz_admin_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: Yanfa2023@
hikari:
#连接池名
pool-name: HikariCP
#最小空闲连接数
minimum-idle: 5
# 空闲连接存活最大时间默认10分钟
idle-timeout: 600000
# 连接池最大连接数默认是10
maximum-pool-size: 10
# 此属性控制从池返回的连接的默认自动提交行为,默认值true
auto-commit: true
# 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟
max-lifetime: 1800000
# 数据库连接超时时间,默认30秒
connection-timeout: 30000
# 连接测试query
connection-test-query: SELECT 1
liquibase:
change-log: classpath:db/changelog/changelog-master.xml
enabled: true
database-change-log-lock-table: databasechangeloglock
database-change-log-table: databasechangelog

@ -0,0 +1,12 @@
oss:
# 支持S3协议的厂商
provider: MINIO
endpoint: 192.168.56.101:9000
accessKey: a4jtJvgEmk4ead5dzac6
secretKey: UW6kxTGRetIAahV759rFkgoQ8ilXLRUMW0ULdIoo
bucketName: test
richtextBucketName: static
domain: http://192.168.56.101:9000
# 命名方式: UUID、ORIGINAL原文件名偏好冲突会补充时间
naming: original
scheme: https

@ -0,0 +1,5 @@
page-helper:
helperDialect: mysql
reasonable: false
supportMethodsArguments: true
params: count=countSql

@ -0,0 +1,28 @@
# redis
spring:
data:
redis:
#单机配置
host: 127.0.0.1
port: 6379
# 数据索引
database: 0
# 连接超时时间(毫秒)
timeout: 50000
###连接池配置###
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 100
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 30
# 连接池中的最小空闲连接
min-idle: 10
password: 123456
# 开启redis监听
redis:
listener:
enable: true

@ -0,0 +1,44 @@
# sa-token
sa-token:
# token名称 (同时也是cookie名称)
token-name: Authorization
# 是否开启自动续签
auto-renew: true
# token固定超时 设为七天 (必定过期) 单位: 秒
timeout: 604800
# 多端不同 token 有效期 可查看 LoginHelper.loginByDevice 方法自定义
# token最低活跃时间 (指定时间无操作就过期) 单位: 秒
active-timeout: 86400
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: true
# jwt秘钥
jwt-secret-key: abcdefghijklmnopqrstuvwxyz
# 允许动态设置 token 有效期
dynamic-active-timeout: true
# 允许从 请求参数 读取 token
is-read-body: false
# 允许从 header 读取 token
is-read-header: true
# 关闭 cookie 鉴权 从根源杜绝 csrf 漏洞风险
is-read-cookie: false
# token前缀
token-prefix: "Bearer"
# 同一账号最大登录数量,-1代表不限
max-login-count: -1
# 接口白名单
router:
whitelist:
- "/v3/api-docs/**"
- "/doc.html"
- "/webjars/**"
- "/swagger-resources"
- "/favicon.ico"
- "/swagger-ui.html"
- "/www/**"
- "/wechat/**"

@ -0,0 +1,30 @@
# swagger文档配置
knife4j:
enable: false
setting:
language: zh_cn
springdoc:
default-flat-param-object: true
swagger-ui:
# 是否开启swagger-ui【生产环境】建议关闭
enabled: false
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha·
api-docs:
# 是否开启api-docs【生产环境】建议关闭
enabled: false
path: /v3/api-docs
group-configs:
- group: 'admin'
paths-to-match: '/**'
packages-to-scan: com.sz.admin
- group: 'generator工具'
paths-to-match: '/**'
packages-to-scan: com.sz.generator
- group: 'www网站'
paths-to-match: '/**'
packages-to-scan: com.sz.www
- group: '微信小程序'
paths-to-match: '/**'
packages-to-scan: com.sz.applet

@ -0,0 +1,10 @@
mybatis-flex:
configuration:
map-underscore-to-camel-case: true
jdbc-type-for-null: null
auto-mapping-behavior: full
auto-mapping-unknown-column-behavior: none
cache-enabled: false
global-config:
deleted-value-of-logic-delete: "T"
normal-value-of-logic-delete: "F"

@ -0,0 +1,28 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/sz_admin_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: Yanfa2023@
hikari:
#连接池名
pool-name: HikariCP
#最小空闲连接数
minimum-idle: 5
# 空闲连接存活最大时间默认10分钟
idle-timeout: 600000
# 连接池最大连接数默认是10
maximum-pool-size: 10
# 此属性控制从池返回的连接的默认自动提交行为,默认值true
auto-commit: true
# 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟
max-lifetime: 1800000
# 数据库连接超时时间,默认30秒
connection-timeout: 30000
# 连接测试query
connection-test-query: SELECT 1
liquibase:
change-log: classpath:db/changelog/changelog-master.xml
enabled: true
database-change-log-lock-table: databasechangeloglock
database-change-log-table: databasechangelog

@ -0,0 +1,12 @@
oss:
# 支持S3协议的厂商
provider: MINIO
endpoint: 192.168.56.101:9000
accessKey: a4jtJvgEmk4ead5dzac6
secretKey: UW6kxTGRetIAahV759rFkgoQ8ilXLRUMW0ULdIoo
bucketName: test
richtextBucketName: static
domain: http://192.168.56.101:9000
# 命名方式: UUID、ORIGINAL原文件名偏好冲突会补充时间
naming: original
scheme: https

@ -0,0 +1,5 @@
page-helper:
helperDialect: mysql
reasonable: false
supportMethodsArguments: true
params: count=countSql

@ -0,0 +1,28 @@
# redis
spring:
data:
redis:
#单机配置
host: 127.0.0.1
port: 6379
# 数据索引
database: 0
# 连接超时时间(毫秒)
timeout: 50000
###连接池配置###
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 100
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 30
# 连接池中的最小空闲连接
min-idle: 10
password: 123456
# 开启redis监听
redis:
listener:
enable: true

@ -0,0 +1,44 @@
# sa-token
sa-token:
# token名称 (同时也是cookie名称)
token-name: Authorization
# 是否开启自动续签
auto-renew: true
# token固定超时 设为七天 (必定过期) 单位: 秒
timeout: 604800
# 多端不同 token 有效期 可查看 LoginHelper.loginByDevice 方法自定义
# token最低活跃时间 (指定时间无操作就过期) 单位: 秒
active-timeout: 86400
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: true
# jwt秘钥
jwt-secret-key: abcdefghijklmnopqrstuvwxyz
# 允许动态设置 token 有效期
dynamic-active-timeout: true
# 允许从 请求参数 读取 token
is-read-body: false
# 允许从 header 读取 token
is-read-header: true
# 关闭 cookie 鉴权 从根源杜绝 csrf 漏洞风险
is-read-cookie: false
# token前缀
token-prefix: "Bearer"
# 同一账号最大登录数量,-1代表不限
max-login-count: -1
# 接口白名单
router:
whitelist:
- "/v3/api-docs/**"
- "/doc.html"
- "/webjars/**"
- "/swagger-resources"
- "/favicon.ico"
- "/swagger-ui.html"
- "/www/**"
- "/wechat/**"

@ -0,0 +1,3 @@
config.stopBubbling=true
# 解决子类警告Generating equals/hashCode implementation but without a call to superclass
lombok.equalsAndHashCode.callSuper=call

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
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>
<groupId>com.sz</groupId>
<artifactId>sz-boot-parent</artifactId>
<packaging>pom</packaging>
<modules>
<module>sz-common</module>
<module>sz-service</module>
<module>sz-dependencies</module>
</modules>
<parent>
<groupId>com.sz</groupId>
<artifactId>sz-build</artifactId>
<version>${revision}</version>
<relativePath>./sz-build/pom.xml</relativePath>
</parent>
<!--配置全局属性-->
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<java.version>21</java.version>
<skipTests>true</skipTests>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.sz</groupId>
<artifactId>sz-dependencies</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--全局通用依赖-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
</dependencies>
<!--maven仓库加速按需引用-->
<!-- <repositories>
&lt;!&ndash;阿里云仓库&ndash;&gt;
<repository>
<id>public</id>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
&lt;!&ndash;华为云仓库&ndash;&gt;
<repository>
<id>huaweicloudmaven</id>
<url>https://repo.huaweicloud.com/maven/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
&lt;!&ndash;腾讯云仓库&ndash;&gt;
<repository>
<id>tencentcloudmaven</id>
<url>https://mirrors.tencent.com/nexus/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
&lt;!&ndash;中科大仓库&ndash;&gt;
<repository>
<id>ustcmaven</id>
<url>https://maven.ustc.edu.cn/maven2/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
&lt;!&ndash; 配置官方Maven中央仓库 &ndash;&gt;
<repository>
<id>central</id>
<url>https://repo1.maven.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>-->
<build>
<plugins>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.44.5</version>
<configuration>
<java>
<encoding>UTF-8</encoding>
<eclipse>
<file>sz-build/baeldung-style.xml</file>
</eclipse>
<removeUnusedImports/>
</java>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,24 @@
<profiles version="21">
<profile kind="CodeFormatterProfile" name="baeldung-style" version="21">
<!--缩进字符:space/tab-->
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<!--用于对缩进和空格进行行包装,默认为FALSE-->
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<!--以在同一行上保留else语句,默认为false-->
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="true"/>
<!--在方法声明中,在参数列表前插入空行-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="1"/>
<!--在第一个类body声明之前添加空行,-默认值:"0"-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="1"/>
<!--用于控制javadoc注释是否被格式化默认为TRUE-->
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<!--代码行的最大长度,当代码行超过这个长度时,格式化工具会尝试在合适的位置进行换行-->
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="160"/>
<!-- other settings... -->
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
</profile>
</profiles>

@ -0,0 +1,24 @@
<?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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.5</version>
<relativePath/>
</parent>
<groupId>com.sz</groupId>
<artifactId>sz-build</artifactId>
<packaging>pom</packaging>
<version>${revision}</version>
<properties>
<!-- sz-boot-parent版本 -->
<revision>1.3.2-beta-SNAPSHOT</revision>
</properties>
</project>

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sz-boot-parent</artifactId>
<groupId>com.sz</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sz-common</artifactId>
<packaging>pom</packaging>
<modules>
<module>sz-common-core</module>
<module>sz-common-db-mongodb</module>
<module>sz-common-db-mysql</module>
<module>sz-common-db-redis</module>
<module>sz-common-excel</module>
<module>sz-common-generator</module>
<module>sz-common-log</module>
<module>sz-common-oss</module>
<module>sz-common-mq</module>
<module>sz-common-security</module>
<module>sz-common-wechat</module>
</modules>
</project>

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sz-common</artifactId>
<groupId>com.sz</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sz-common-core</artifactId>
<dependencies>
<!-- springboot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- pagehelper 分页-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- apache commons工具包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- valid 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- jackson扩展 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- websocket依赖以后有可能将websocket相关工具提取到独立模块 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-starter</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency>
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,27 @@
package com.sz.core.common.annotation;
import java.lang.annotation.*;
/**
*
* <p>
*
* </p>
*
* @author sz
* @version 1.0
* @since 2024/9/18
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
public @interface Debounce {
/**
* 1000 ms
*
* @return ms
*/
long time() default 1000;
}

@ -0,0 +1,19 @@
package com.sz.core.common.annotation;
import java.lang.annotation.*;
/**
*
*
* @author sz
* @version 1.0
* @since 2024/9/18
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
public @interface DebounceIgnore {
boolean required() default true;
}

@ -0,0 +1,158 @@
package com.sz.core.common.configuration;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.sz.core.common.entity.MultipartFileSerializer;
import com.sz.core.common.jackson.EmptySerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.TimeZone;
/**
* Jackson
* <p>
* - Null - date - - -
* </p>
*
* @author sz
* @version 1.0
* @since 2022/8/26
*/
@Configuration
@JsonComponent
@Slf4j
public class JacksonConfiguration extends JsonSerializer<LocalDateTime> {
private static final String TIME_ZONE = "GMT+8";
private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
private static final String DATE_PATTERN = "yyyy-MM-dd";
private static final long JS_SAFE_INTEGER_MAX = 9007199254740991L;
private static final long JS_SAFE_INTEGER_MIN = -9007199254740991L;
@Bean
public Converter<String, LocalDate> localDateConverter() {
return new Converter<String, LocalDate>() {
@Override
public LocalDate convert(String source) {
if (source.trim().isEmpty()) {
return null;
}
try {
return LocalDate.parse(source);
} catch (Exception e) {
return LocalDate.parse(source, DateTimeFormatter.ofPattern(DATE_PATTERN));
}
}
};
}
@Bean
public Converter<String, LocalDateTime> localDateTimeConverter() {
return new Converter<String, LocalDateTime>() {
@Override
public LocalDateTime convert(String source) {
if (source.trim().isEmpty()) {
return null;
}
try {
return LocalDateTime.parse(source);
} catch (Exception e) {
return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DATE_TIME_PATTERN));
}
}
};
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN)));
return builder -> {
builder.modules(javaTimeModule);
builder.simpleDateFormat(DATE_TIME_PATTERN);
builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_PATTERN)));
builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN)));
};
}
@Bean
@Primary
@ConditionalOnMissingBean(ObjectMapper.class)
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
objectMapper.setTimeZone(TimeZone.getTimeZone(TIME_ZONE)); // 指定时区为:中国时
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 针对实体映射时不匹配类型或序列化的处理配置:即找不到、不可用也不抛出异常。
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.setSerializerFactory(objectMapper.getSerializerFactory().withSerializerModifier(new BeanSerializerModifier() {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
for (BeanPropertyWriter writer : beanProperties) {
JavaType type = writer.getType();
if (type.isTypeOrSubTypeOf(String.class)) {
writer.assignNullSerializer(EmptySerializer.EmptyStringSerializer.INSTANCE);
} else if (type.isCollectionLikeType()) {
writer.assignNullSerializer(EmptySerializer.EmptyArraySerializer.INSTANCE);
} else if (type.isMapLikeType()) {
writer.assignNullSerializer(EmptySerializer.EmptyObjectSerializer.INSTANCE);
} else {
// default fallback
writer.assignNullSerializer(EmptySerializer.EmptyStringSerializer.INSTANCE);
}
}
return beanProperties;
}
}));
// 对MultipleFile序列化的支持
SimpleModule module = new SimpleModule();
module.addSerializer(MultipartFile.class, new MultipartFileSerializer());
// 添加Long类型的自定义序列化器
module.addSerializer(Long.class, new JsonSerializer<>() {
@Override
public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value > JS_SAFE_INTEGER_MAX || value < JS_SAFE_INTEGER_MIN) {
gen.writeString(value.toString());
} else {
gen.writeNumber(value);
}
}
});
objectMapper.registerModule(module);
return objectMapper;
}
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
String formattedValue = value.format(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN));
gen.writeString(formattedValue);
}
}

@ -0,0 +1,53 @@
package com.sz.core.common.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 线
*
* @author sz
* @version 1.0
* @since 2022/8/29
*/
@EnableAsync
@Configuration
public class ThreadTaskConfiguration {
private static final String THREAD_NAME_PREFIX = "sz-admin-thread_";
@Bean
public Executor taskExecutor() {
// 根据ThreadPoolTaskExecutor 创建建线程池
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 为线程设置初始的线程数量
executor.setCorePoolSize(5);
// 为线程设置最大的线程数量
executor.setMaxPoolSize(30);
// 为任务队列设置最大Queue数量
executor.setQueueCapacity(200);
// 设置 超出初始化线程的 存在时间为60秒
// 也就是 如果现有线程数超过corePoolSize 则会对超出的空闲线程 设置摧毁时间 也就是60秒
executor.setKeepAliveSeconds(60);
// 设置 线程前缀
executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
// 线程池的饱和策略 我这里设置的是 CallerRunsPolicy 也就是由用调用者所在的线程来执行任务 共有四种
// AbortPolicy直接抛出异常这是默认策略
// CallerRunsPolicy用调用者所在的线程来执行任务
// DiscardOldestPolicy丢弃阻塞队列中靠最前的任务并执行当前任务
// DiscardPolicy直接丢弃任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 设置在关闭线程池时是否等待任务完成
executor.setWaitForTasksToCompleteOnShutdown(true);
// 设置等待终止的秒数
executor.setAwaitTerminationSeconds(60);
// 返回设置完成的线程池
return executor;
}
}

@ -0,0 +1,36 @@
package com.sz.core.common.configuration;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/**
*
* @author sz
* @version 1.0
* @since 2022/8/29
*/
@Configuration
@RequiredArgsConstructor
public class WebMvcConfiguration implements WebMvcConfigurer {
private final ObjectProvider<HttpMessageConverters> messageConverters;
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// 将你自定义的转换器加到现有列表中
this.messageConverters.ifAvailable(customConverters -> converters.addAll(customConverters.getConverters()));
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}

@ -0,0 +1,43 @@
package com.sz.core.common.constant;
/**
*
*
* @author sz
* @version 1.0
* @since 2022/8/23
*/
public class GlobalConstant {
private GlobalConstant() {
throw new IllegalStateException("GlobalConstant class Illegal");
}
public static final String UTF_8 = "utf-8";
/**
* redischannel [->websocket]
*/
public static final String SERVICE_TO_WS = "channel:service_to_ws";
/**
* redischannel [websocket->]
*/
public static final String WS_TO_SERVICE = "channel:ws_to_service";
/**
* redischannel permission
*/
public static final String CHANGE_PERMISSIONS_SIGNAL = "change_permissions_signal";
/**
*
*/
public static final String SUPER_ROLE = "admin";
/**
*
*/
public static final String DYNAMIC_DICT_PREFIX = "dynamic_";
}

@ -0,0 +1,30 @@
package com.sz.core.common.dict;
import com.sz.core.common.entity.DictVO;
import java.util.List;
import java.util.Map;
/**
*
*/
public interface DictLoader {
/**
* Map
*
* @return Mapkey typeCodevalue DictVO
*/
Map<String, List<DictVO>> loadDict();
/**
* typeCodeDict
*
* @param typeCode
*
* @return DictVO
*/
default List<DictVO> getDict(String typeCode) {
return loadDict().get(typeCode);
}
}

@ -0,0 +1,88 @@
package com.sz.core.common.dict;
import com.sz.core.common.entity.DictVO;
import com.sz.core.util.SpringApplicationContextUtils;
import com.sz.core.util.Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class DictLoaderFactory {
// 动态字典加载器
private final List<DynamicDictLoader> dynamicLoaders = new ArrayList<>();
// 唯一的静态字典加载器
private final DictLoader defaultLoader;
@Autowired
public DictLoaderFactory(List<DictLoader> allLoaders) {
DictLoader foundDefault = null;
for (DictLoader loader : allLoaders) {
if (loader instanceof DynamicDictLoader dynamicLoader) {
if (Utils.isNotNull(dynamicLoader.getDynamicTypeCode())) {
dynamicLoaders.add(dynamicLoader);
}
} else {
if (foundDefault == null) {
foundDefault = loader;
}
}
}
this.defaultLoader = foundDefault;
}
/**
* +
*
* @return Map
*/
public Map<String, List<DictVO>> loadAllDict() {
Map<String, List<DictVO>> result = defaultLoader != null ? new HashMap<>(defaultLoader.loadDict()) : new HashMap<>();
for (DynamicDictLoader loader : dynamicLoaders) {
result.putAll(loader.loadDict());
}
return result;
}
/**
*
*
* @param typeCode
*
* @return DictVO
*/
public List<DictVO> getDictByType(String typeCode) {
Map<String, List<DictVO>> allDict = loadAllDict();
if (!allDict.containsKey(typeCode)) {
if (typeCode.contains("dynamic_")) {
return List.of();
}
return defaultLoader != null ? defaultLoader.getDict(typeCode) : List.of();
}
return allDict.get(typeCode);
}
/**
* +
*
* @return DictTypeVO
*/
public List<DictTypeVO> getAllDictType() {
DictTypeService dictTypeService = SpringApplicationContextUtils.getInstance().getBean(DictTypeService.class);
List<DictTypeVO> result = new ArrayList<>(dictTypeService.findDictType());
for (DynamicDictLoader loader : dynamicLoaders) {
String typeCode = loader.getDynamicTypeCode();
String name = loader.getTypeName();
DictTypeVO dictTypeVO = DictTypeVO.builder().typeName(name).typeCode(typeCode).isDynamic(true).build();
result.add(dictTypeVO);
}
return result;
}
}

@ -0,0 +1,89 @@
package com.sz.core.common.dict;
import com.sz.core.common.entity.DictVO;
import java.util.List;
import java.util.Map;
/**
*
*
* @author sz
* @since 2023/12/26 16:38
*/
public interface DictService {
/**
*
*/
String SEPARATOR = ",";
/**
*
*
* @param dictType
*
* @param dictValue
*
* @return
*/
default String getDictLabel(String dictType, String dictValue) {
return getDictLabel(dictType, dictValue, SEPARATOR);
}
/**
*
*
* @param dictType
*
* @param dictLabel
*
* @return
*/
default String getDictValue(String dictType, String dictLabel) {
return getDictValue(dictType, dictLabel, SEPARATOR);
}
/**
*
*
* @param dictType
*
* @param dictValue
*
* @param separator
*
* @return
*/
String getDictLabel(String dictType, String dictValue, String separator);
/**
*
*
* @param dictType
*
* @param dictLabel
*
* @param separator
*
* @return
*/
String getDictValue(String dictType, String dictLabel, String separator);
/**
*
*
* @param dictType
*
* @return dictValuekeydictLabelMap
*/
Map<String, String> getAllDictByType(String dictType);
/**
*
*
* @return keyMap
*/
Map<String, List<DictVO>> getAllDict();
}

@ -0,0 +1,8 @@
package com.sz.core.common.dict;
import java.util.List;
public interface DictTypeService {
List<DictTypeVO> findDictType();
}

@ -0,0 +1,30 @@
package com.sz.core.common.dict;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
/**
* DictTypeVO
*
* @author sz
* @since 2024/8/22 11:17
* @version 1.0
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DictTypeVO {
@Schema(description = "字典类型code")
private String typeCode;
@Schema(description = "字典类型名称")
private String typeName;
@Schema(description = "是否是动态字典")
@JsonProperty("isDynamic")
private boolean isDynamic = false;
}

@ -0,0 +1,33 @@
package com.sz.core.common.dict;
import static com.sz.core.common.constant.GlobalConstant.DYNAMIC_DICT_PREFIX;
/**
* loader
*/
public interface DynamicDictLoader extends DictLoader {
/**
* typeCode
*/
String getTypeCode();
/**
* typeName
*/
String getTypeName();
/**
*
*/
default String getDynamicPrefix() {
return DYNAMIC_DICT_PREFIX;
}
/**
* typeCode
*/
default String getDynamicTypeCode() {
return getDynamicPrefix() + getTypeCode();
}
}

@ -0,0 +1,59 @@
package com.sz.core.common.entity;
import lombok.Data;
import lombok.experimental.SuperBuilder;
/**
* @author sz
* @since 2022/02/16 09:39
*/
@Data
@SuperBuilder
public class AccessRequestLog {
private String type = "request";
/**
*
*/
private String traceId;
private String userId;
/**
*
*/
private String url;
/**
*
*/
private long timestamp;
/**
* http GETPOST
*/
private String method;
/**
* url
*/
private Object param;
/**
* form
*/
private Object form;
/**
* post body
*/
private Object body;
private String ip;
private String contentType;
private Object requestBody;
}

@ -0,0 +1,58 @@
package com.sz.core.common.entity;
import lombok.Data;
import lombok.experimental.SuperBuilder;
/**
* @author sz
* @since 2023/2/20 16:33
*/
@Data
@SuperBuilder
public class AccessResponseLog {
private String traceId;
/**
*
*/
private long timestamp;
private String userId;
/**
*
*/
private String url;
/**
* (ms)
*/
private long ms;
/**
*
*/
private Object resBody;
/**
* url
*/
private Object param;
/**
* form
*/
private Object form;
/**
* post body
*/
private Object reqBody;
private String type = "response";
private String method;
}

@ -0,0 +1,55 @@
package com.sz.core.common.entity;
import com.mybatisflex.core.paginate.Page;
import com.sz.core.common.enums.CommonResponseEnum;
import com.sz.core.util.PageUtils;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
*
*
* @author sz
* @version 1.0
* @since 2022/8/23
*/
@Data
public class ApiPageResult<T> extends ApiResult<T> implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
public static <T> ApiResult<PageResult<T>> success(List<T> data) {
ApiResult<PageResult<T>> apiResult = new ApiPageResult<>();
apiResult.data = (data != null) ? PageUtils.getPageResult(data) : PageUtils.getPageResult(new ArrayList<>());
return apiResult;
}
public static <T> ApiResult<PageResult<T>> success(Page<T> page) {
return success(PageUtils.getPageResult(page));
}
public static <T> ApiResult<PageResult<T>> success(List<T> data, Object param) {
ApiResult<PageResult<T>> apiResult = new ApiPageResult<>();
apiResult.data = (data != null) ? PageUtils.getPageResult(data) : PageUtils.getPageResult(new ArrayList<>());
apiResult.setParam(param);
return apiResult;
}
public static <T> ApiPageResult<PageResult<T>> success(PageResult<T> data) {
ApiPageResult<PageResult<T>> apiResult = new ApiPageResult<>();
apiResult.data = (data != null) ? data : PageUtils.getPageResult(new ArrayList<>());
return apiResult;
}
public static <T> ApiPageResult<T> error(CommonResponseEnum responseEnum) {
ApiPageResult<T> apiResult = new ApiPageResult<>();
apiResult.setCode(getResponseCode(responseEnum));
apiResult.setMessage(responseEnum.getMessage());
return apiResult;
}
}

@ -0,0 +1,92 @@
package com.sz.core.common.entity;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.sz.core.common.enums.CommonResponseEnum;
import com.sz.core.common.exception.common.BusinessExceptionCustomAssert;
import com.sz.core.util.Utils;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* ApiResult
*
* @author sz
* @version 1.0
* @since 2025/1/12
*/
@JsonInclude(JsonInclude.Include.USE_DEFAULTS)
@Data
public class ApiResult<T> implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "自定义响应码", example = "0000")
public String code = "0000";
@Schema(description = "响应信息", example = "SUCCESS")
public String message = "SUCCESS";
@Schema(description = "响应数据")
public T data;
@Schema(description = "额外参数")
private Object param = new Object();
public ApiResult() {
}
public ApiResult(String code, String message) {
this.code = code;
this.message = message;
}
public static <T> ApiResult<T> success() {
ApiResult<T> apiResult = new ApiResult<>();
apiResult.data = null;
return apiResult;
}
public static <T> ApiResult<T> success(T data) {
ApiResult<T> apiResult = new ApiResult<>();
apiResult.data = data;
return apiResult;
}
public static <T> ApiResult<T> success(T data, Object param) {
ApiResult<T> apiResult = new ApiResult<>();
apiResult.data = data;
if (Utils.isNotNull(param)) {
apiResult.param = param;
}
return apiResult;
}
public static <T> ApiResult<T> error(CommonResponseEnum responseEnum) {
ApiResult<T> apiResult = new ApiResult<>();
apiResult.code = getResponseCode(responseEnum);
apiResult.message = responseEnum.getMessage();
apiResult.data = null;
return apiResult;
}
protected static String getResponseCode(CommonResponseEnum responseEnum) {
return responseEnum.getCodePrefixEnum().getPrefix() + responseEnum.getCode();
}
public static <T> ApiResult<T> error(BusinessExceptionCustomAssert responseEnum) {
ApiResult<T> apiResult = new ApiResult<>();
apiResult.code = getResponseCode(responseEnum);
apiResult.message = responseEnum.getMessage();
apiResult.data = null;
return apiResult;
}
protected static String getResponseCode(BusinessExceptionCustomAssert responseEnum) {
return responseEnum.getCodePrefixEnum().getPrefix() + responseEnum.getCode();
}
}

@ -0,0 +1,34 @@
package com.sz.core.common.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* BaseUserInfo -
*
* @author sz
* @version 1.0
* @since 2023-12-12
*/
@Data
public class BaseUserInfo {
@Schema(description = "用户id")
private Long id;
@Schema(description = "用户名")
private String username;
@Schema(description = "昵称")
private String nickname;
@Schema(description = "手机号")
private String phone;
@Schema(description = "LOGO")
private String logo;
@Schema(description = "邮箱")
private String email;
}

@ -0,0 +1,25 @@
package com.sz.core.common.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* CheckPuzzle
*
* @version 1.0
* @since 2025-01-08
* @author sz
*/
@Data
public class CheckPuzzle {
@Schema(description = "请求标识")
private String requestId;
@Schema(description = "移动变量x轴位置加密串")
private String moveEncrypted;
@Schema(description = "iv向量")
private String iv;
}

@ -0,0 +1,16 @@
package com.sz.core.common.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@AllArgsConstructor
@Data
public class ControlPermissions {
private String[] permissions;
private String mode;
}

@ -0,0 +1,49 @@
package com.sz.core.common.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DictVO {
@Schema(description = "字典id", example = "1000001")
private String id;
@Schema(description = "字典类型id", example = "1000")
private Long sysDictTypeId;
@Schema(description = "字典名称", example = "正常")
private String codeName;
@Schema(description = "别名", example = "normal")
private String alias;
@Schema(description = "排序", example = "1")
private Integer sort;
@Schema(description = "回显样式", example = "success", allowableValues = "success,info,warning,danger")
private String callbackShowStyle;
@Schema(description = "是否锁定", example = "F", allowableValues = "T,F")
private String isLock;
@Schema(description = "是否展示", example = "T", allowableValues = "T,F")
private String isShow;
@Schema(description = "字典类型名", example = "账户状态")
private String sysDictTypeName;
@Schema(description = "字典类型码", example = "account_status")
private String sysDictTypeCode;
@Schema(description = "是否动态字典")
@JsonProperty("isDynamic")
private boolean isDynamic = false;
}

@ -0,0 +1,15 @@
package com.sz.core.common.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
@Data
public class ImportExcelDTO {
private MultipartFile file;
@Schema(description = "是否数据覆盖", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean isCover;
}

@ -0,0 +1,32 @@
package com.sz.core.common.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.*;
@Data
public class LoginUser {
@Schema(description = "基础用户信息")
private BaseUserInfo userInfo;
@Schema(description = "权限标识列表")
private Set<String> permissions = new HashSet<>();
@Schema(description = "角色列表")
private Set<String> roles = new HashSet<>();
@Schema(description = "所属部门")
private List<Long> depts = new ArrayList<>();
@Schema(description = "所属部门及其子孙节点部门")
private List<Long> deptAndChildren = new ArrayList<>();
@Schema(description = "权限标识与菜单关系数组")
private Map<String, String> permissionAndMenuIds = new HashMap<>();
@Schema(description = "数据权限范围")
private Map<String, RoleMenuScopeVO> dataScope;
}

@ -0,0 +1,19 @@
package com.sz.core.common.entity;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
* MultipleFile
*/
public class MultipartFileSerializer extends JsonSerializer<MultipartFile> {
@Override
public void serialize(MultipartFile value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(value.getOriginalFilename());
}
}

@ -0,0 +1,21 @@
package com.sz.core.common.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
*
*
* @author sz
* @since 2022/8/25 15:58
*/
@Data
public class PageQuery {
@Schema(description = "页数", example = "1")
private Integer page = 1;
@Schema(description = "每页条数", example = "10")
private Integer limit = 10;
}

@ -0,0 +1,44 @@
package com.sz.core.common.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
*
*
* @author sz
* @since 2022/8/25 10:25
*/
@Data
public class PageResult<T> implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "当前页")
private long current;
@Schema(description = "每页条数")
private long limit;
@Schema(description = "总页数")
private long totalPage;
@Schema(description = "总条数")
private long total;
@Schema(description = "结果集")
private List<T> rows;
public PageResult(long current, long limit, long totalPage, long total, List<T> rows) {
this.current = current;
this.limit = limit;
this.totalPage = totalPage;
this.total = total;
this.rows = rows;
}
}

@ -0,0 +1,16 @@
package com.sz.core.common.entity;
import lombok.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PointVO {
private int x;
private int y;
private String secretKey;
}

@ -0,0 +1,32 @@
package com.sz.core.common.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Collection;
@Schema(description = "用户的数据权限范围汇总信息")
@Data
public class RoleMenuScopeVO {
@Schema(description = "sys_menu_id (菜单表)")
private String menuId;
@Schema(description = "数据权限范围")
private String dataScopeCd;
@Schema(description = "自定义数据权限范围当dataScopeCd为1006005时使用")
private CustomScope customScope;
@Data
public static class CustomScope {
@Schema(description = "用户ID")
private Collection<Long> userIds;
@Schema(description = "部门ID")
private Collection<Long> deptIds;
}
}

@ -0,0 +1,23 @@
package com.sz.core.common.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Data
public class SelectIdsDTO {
@Schema(description = "选择的标识数组")
private List<? extends Serializable> ids = new ArrayList<>();
public SelectIdsDTO() {
}
public SelectIdsDTO(List<? extends Serializable> ids) {
this.ids = ids;
}
}

@ -0,0 +1,38 @@
package com.sz.core.common.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class SliderPuzzle {
@Schema(description = "请求ID")
private String requestId;
@Schema(description = "大图宽度")
private Integer bigWidth;
@Schema(description = "大图高度")
private Integer bigHeight;
@Schema(description = "大图转BASE64字符串")
private String bigImageBase64;
@Schema(description = "小图宽度")
private Integer smallWidth;
@Schema(description = "小图高度")
private Integer smallHeight;
@Schema(description = "小图转BASE64字符串")
private String smallImageBase64;
@Schema(description = "随机坐标Y")
private Integer posY;
@Schema(description = "随机坐标X")
private Integer posX;
@Schema(description = "加密key")
private String secretKey;
}

@ -0,0 +1,30 @@
package com.sz.core.common.entity;
import com.sz.core.common.enums.MessageTransferScopeEnum;
import com.sz.core.common.enums.SocketChannelEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sz
* @since 2023/9/6 17:20
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SocketMessage {
@Schema(description = "data")
protected Object data;
@Schema(description = "通道类型")
protected SocketChannelEnum channel = SocketChannelEnum.DEFAULTS;
@Schema(description = "消息通知作用域")
protected MessageTransferScopeEnum scope = MessageTransferScopeEnum.SOCKET_CLIENT;
}

@ -0,0 +1,34 @@
package com.sz.core.common.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
/**
* @author sz
* @since 2023/9/8 16:10
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TransferMessage {
@Schema(description = "消息体bean")
private SocketMessage message;
@Schema(description = "消息接收人")
private List<?> toUsers = new ArrayList<>();
@Schema(description = "消息发送人")
private String fromUser;
@Schema(description = "是否通知全部用户")
private boolean toPushAll = false;
}

@ -0,0 +1,46 @@
package com.sz.core.common.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
/**
* @author sz
* @since 2024/11/12 16:22
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UploadResult {
// URL
private String url;
// 文件名
private String filename;
// 对象名称 (带路径)
private String objectName;
// 标记
private String eTag;
// 标记
private String dirTag;
// 文件类型
private String contextType;
// 文件大小
private Long size;
// 文件id
private Long fileId;
// 元数据
private Map<String, String> metaData;
}

@ -0,0 +1,34 @@
package com.sz.core.common.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class UserPermissionChangeMessage {
@Schema(description = "username")
private String username;
@Schema(description = "用户id")
private Long userId;
/**
* permission
*/
private boolean toChangeAll;
public UserPermissionChangeMessage() {
}
public UserPermissionChangeMessage(String username, Long userId, boolean toChangeAll) {
this.username = username;
this.userId = userId;
this.toChangeAll = toChangeAll;
}
public UserPermissionChangeMessage(String username, boolean toChangeAll) {
this.username = username;
this.toChangeAll = toChangeAll;
}
}

@ -0,0 +1,28 @@
package com.sz.core.common.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.web.socket.WebSocketSession;
/**
* @author sz
* @since 2023/9/8 8:32
*/
@Data
public class WsSession {
@Schema(description = "sid,自定义生成的uuid")
private String sid;
@Schema(description = "loginId")
private String loginId;
@Schema(description = "socket-session")
private WebSocketSession session;
public WsSession(String sid, String loginId, WebSocketSession session) {
this.sid = sid;
this.loginId = loginId;
this.session = session;
}
}

@ -0,0 +1,72 @@
package com.sz.core.common.enums;
/**
*
*/
public enum CommonResponseEnum implements ResponseEnumTemplate<CommonResponseEnum> {
// @formatter:off
VALID_ERROR(100, "参数校验异常"),
BAD_USERNAME_OR_PASSWORD(101, "账户不存在或密码错误"),
CNT_PASSWORD_ERR(102, "密码错误次数过多,账户锁定!"),
CLIENT_INVALID(103, "无效的ClientId"),
CLIENT_BLOCKED(104, "Client认证已禁用"),
INVALID_TOKEN(105, "无效Token"),
INVALID_USER(106, "无效用户"),
BAD_USERNAME_STATUS_INVALID(107, "用户被禁用"),
INVALID_PERMISSION(108, "抱歉,您目前无权执行此操作,请联系管理员获取相应权限。"),
WEBSOCKET_SEND_FAIL(109, "WebSocket消息发送异常"),
DEBOUNCE(110, "您的请求过于频繁,请稍后再试!"),
MEDIA_HTTP_FAIL(602,"流媒体服务器调用失败"),
INVALID_ID(1000, "无效ID"),
EXISTS(1001, "已存在"),
NOT_EXISTS(1002, "不存在"),
FILE_NOT_EXISTS(1003, "文件不存在"),
FILE_UPLOAD_EXT_ERROR(1004, "上传文件类型错误"),
FILE_UPLOAD_SIZE_ERROR(1005, "上传文件大小不能超过10MB"),
FILE_UPLOAD_ERROR(1006, "上传文件失败"),
USERNAME_EXISTS(1007, "用户名已存在"),
INVALID(1008, "无效的数据"),
EXCEL_IMPORT_ERROR(1009, "Excel导入失败"),
CAPTCHA_LACK(1010, "验证参数缺失"),
CAPTCHA_EXPIRED(1011, "验证码失效,请重新获取"),
CAPTCHA_FAILED(1012, "验证失败"),
CAPTCHA_LIMIT(1013,"验证码请求已达到最大次数"),
BACKGROUND_NOT_EXISTS(1014, "背景图片不存在"),
LOGIN_LIMIT(1015,"登录请求已达到最大次数"),
UNKNOWN(9999, "未知异常"),
;
// @formatter:on
/**
*
*/
private final int code;
/**
*
*/
private final String message;
CommonResponseEnum(int code, String message) {
this.code = code;
this.message = message;
}
@Override
public int getCode() {
return this.code;
}
@Override
public String getMessage() {
return this.message;
}
@Override
public ErrorPrefixEnum getCodePrefixEnum() {
return ErrorPrefixEnum.COMMON;
}
}

@ -0,0 +1,40 @@
package com.sz.core.common.enums;
import lombok.Getter;
/**
* ErrorPrefixEnum -
* <p>
* 便
* </p>
*
* @version 1.0
* @since 2024-10-11
* @author sz
*/
@Getter
public enum ErrorPrefixEnum {
// @formatter:off
COMMON("C", "common异常"),
ADMIN("A", "admin异常"),
// ...其他业务模块的异常前缀
;
// @formatter:on
/**
*
*/
private final String prefix;
/**
*
*/
private final String description;
ErrorPrefixEnum(String prefix, String description) {
this.prefix = prefix;
this.description = description;
}
}

@ -0,0 +1,18 @@
package com.sz.core.common.enums;
/**
* MessageTransferScopeEnum -
*
* @version 1.0
* @since 2024-02-17
* @author sz
*/
public enum MessageTransferScopeEnum {
// 后台服务端
SERVER,
// socket服务端
SOCKET_SERVER,
// socket客户端 web、app等
SOCKET_CLIENT,
}

@ -0,0 +1,51 @@
package com.sz.core.common.enums;
import com.sz.core.common.exception.common.BusinessExceptionCustomAssert;
/**
* 线message
*
* @param <E>
*
*/
public interface ResponseEnumTemplate<E extends Enum<E> & ResponseEnumTemplate<E>> extends BusinessExceptionCustomAssert {
class CustomMessageWrapper<T extends Enum<T> & ResponseEnumTemplate<T>> implements BusinessExceptionCustomAssert {
private final T original;
private final int customCode;
private final String customMessage;
public CustomMessageWrapper(T original, int customCode, String customMessage) {
this.original = original;
this.customCode = customCode;
this.customMessage = customMessage;
}
@Override
public int getCode() {
return this.customCode;
}
@Override
public String getMessage() {
return this.customMessage;
}
@Override
public ErrorPrefixEnum getCodePrefixEnum() {
return original.getCodePrefixEnum();
}
}
@SuppressWarnings("unchecked")
default BusinessExceptionCustomAssert message(int code, String message) {
return new CustomMessageWrapper<>((E) this, code, message);
}
default BusinessExceptionCustomAssert message(String message) {
return message(getCode(), message);
}
}

@ -0,0 +1,48 @@
package com.sz.core.common.enums;
import lombok.Getter;
/**
* @author sz
* @since 2023/9/6 10:24
*/
@Getter
public enum SocketChannelEnum {
// @formatter:off
DEFAULTS("default", "默认channel", "push_or_receive"),
AUTH("auth", "鉴权", "push_or_receive"),
CLOSE("close", "断开连接", "push"),
KICK_OFF("kick_off", "踢下线", "push"),
SYNC_MENU("sync_menu", "同步菜单", "push"),
SYNC_DICT("sync_dict", "同步字典", "push"),
SYNC_PERMISSIONS("sync_permissions", "同步permission权限", "push"),
UPGRADE_CHANNEL("upgrade_channel", "升级通告", "push"),
MESSAGE("message", "系统消息", "push"),
READ("read","消息已读刷新数量","push"),
TEST("test","测试","push"),
SYNC_FRONTEND_CONF("sync_frontend_conf","同步前端配置","push"),
;
// @formatter:on
/**
*
*/
private final String name;
/**
*
*/
private final String remark;
/**
* push 1 receive2 push_or_receive
*/
private final String status;
SocketChannelEnum(String name, String remark, String status) {
this.name = name;
this.remark = remark;
this.status = status;
}
}

@ -0,0 +1,5 @@
package com.sz.core.common.enums;
public enum TrueFalseEnum {
T, F
}

@ -0,0 +1,16 @@
package com.sz.core.common.event;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
@Getter
public abstract class BaseEvent<T> extends ApplicationEvent {
private final T payload;
protected BaseEvent(Object source, T payload) {
super(source);
this.payload = payload;
}
}

@ -0,0 +1,22 @@
package com.sz.core.common.event;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
/**
* @version 1.0
* @since 2024-02-29
* @author sz
*/
@Component
@RequiredArgsConstructor
public class EventPublisher {
private final ApplicationEventPublisher applicationEventPublisher;
public void publish(BaseEvent<?> event) {
applicationEventPublisher.publishEvent(event);
}
}

@ -0,0 +1,104 @@
package com.sz.core.common.exception;
import com.sz.core.common.entity.ApiResult;
import com.sz.core.common.enums.CommonResponseEnum;
import com.sz.core.common.exception.common.BaseException;
import com.sz.core.common.exception.common.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
*
*
* @author sz
* @since 2022/8/23 10:56
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<ApiResult<Object>> exceptionHandler(Exception e) {
log.error(e.getMessage(), e);
ApiResult<Object> error = ApiResult.error(CommonResponseEnum.UNKNOWN);
return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
/**
*
*
* @param e
*
* @return
*/
@ExceptionHandler(value = BusinessException.class)
@ResponseBody
public ApiResult<Void> handleBusinessException(BusinessException e) {
log.error(e.getMessage(), e);
return new ApiResult<>(getCode(e), e.getMessage());
}
/**
*
*
* @param e
*
* @return
*/
@ExceptionHandler(value = BaseException.class)
@ResponseBody
public ApiResult<Void> handleBaseException(BaseException e) {
log.error(e.getMessage(), e);
return new ApiResult<>(getCode(e), e.getMessage());
}
/**
*
*
* @param e
*
* @return
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public ResponseEntity<ApiResult<Object>> handleValidException(MethodArgumentNotValidException e) {
log.error(e.getMessage(), e);
ApiResult<Object> apiResult = wrapperBindingResult(e);
return new ResponseEntity<>(apiResult, HttpStatus.UNPROCESSABLE_ENTITY);
}
/**
*
*
* @param e
*
* @return
*/
@ExceptionHandler(value = BindException.class)
public ResponseEntity<ApiResult<Object>> handleBindException(BindException e) {
log.error(e.getMessage(), e);
ApiResult<Object> apiResult = wrapperBindingResult(e);
return new ResponseEntity<>(apiResult, HttpStatus.UNPROCESSABLE_ENTITY);
}
private ApiResult<Object> wrapperBindingResult(BindingResult bindingResult) {
StringBuilder msg = new StringBuilder();
for (ObjectError error : bindingResult.getAllErrors()) {
msg.append(", ");
msg.append(error.getDefaultMessage() == null ? "" : error.getDefaultMessage());
}
return new ApiResult<>(CommonResponseEnum.VALID_ERROR.getCodePrefixEnum().getPrefix() + CommonResponseEnum.VALID_ERROR.getCode(), msg.substring(2));
}
private String getCode(BaseException e) {
return e.getResponseEnum().getCodePrefixEnum().getPrefix() + e.getResponseEnum().getCode();
}
}

@ -0,0 +1,29 @@
package com.sz.core.common.exception.common;
import lombok.Getter;
import java.io.Serial;
@Getter
public class BaseException extends RuntimeException {
@Serial
private static final long serialVersionUID = 1L;
private final IResponseEnum responseEnum;
private final Object[] args;
public BaseException(IResponseEnum responseEnum, Object[] args, String message) {
super(message);
this.responseEnum = responseEnum;
this.args = args;
}
public BaseException(IResponseEnum responseEnum, Object[] args, String message, Throwable cause) {
super(message, cause);
this.responseEnum = responseEnum;
this.args = args;
}
}

@ -0,0 +1,16 @@
package com.sz.core.common.exception.common;
import java.io.Serial;
public class BusinessException extends BaseException {
@Serial
private static final long serialVersionUID = 1L;
public BusinessException(IResponseEnum responseEnum, Object[] args, String message) {
super(responseEnum, args, message);
}
public BusinessException(IResponseEnum responseEnum, Object[] args, String message, Throwable cause) {
super(responseEnum, args, message, cause);
}
}

@ -0,0 +1,33 @@
package com.sz.core.common.exception.common;
import java.text.MessageFormat;
public interface BusinessExceptionCustomAssert extends IResponseEnum, CustomAssert {
@Override
default BaseException newException(Object... args) {
String msg = MessageFormat.format(this.getMessage(), args);
return new BusinessException(this, args, msg);
}
@Override
default BaseException newException(Throwable t, Object... args) {
String msg = MessageFormat.format(this.getMessage(), args);
return new BusinessException(this, args, msg, t);
}
/**
* messageargs
*
* @param message
*
* @param args
* message
* @return
*/
default BaseException newException(String message, Object... args) {
String formattedMessage = MessageFormat.format(message, args);
return new BaseException(this, args, formattedMessage);
}
}

@ -0,0 +1,85 @@
package com.sz.core.common.exception.common;
public interface CustomAssert {
/**
*
*
* @param args
*
* @return
*/
BaseException newException(Object... args);
/**
*
*
* @param t
* Throwable
* @param args
*
* @return
*/
BaseException newException(Throwable t, Object... args);
/**
* <p>
* <code>obj</code><code>obj</code>
*
* @param obj
*
*/
default void assertNull(Object obj) {
if (obj == null) {
throw newException();
}
}
default void assertNotNull(Object obj) {
if (obj != null) {
throw newException();
}
}
/**
* boolean true
*
* @param bool
* boolean
*/
default void assertTrue(boolean bool) {
if (bool) {
throw newException();
}
}
/**
* boolean false
*
* @param bool
* boolean
*/
default void assertFalse(boolean bool) {
if (!bool) {
throw newException();
}
}
/**
* <p>
* <code>obj</code><code>obj</code>
* <p>
* <code>message</code>
*
* @param obj
*
* @param args
* message
*/
default void assertNull(Object obj, Object... args) {
if (obj == null) {
throw newException(args);
}
}
}

@ -0,0 +1,28 @@
package com.sz.core.common.exception.common;
import com.sz.core.common.enums.ErrorPrefixEnum;
public interface IResponseEnum {
/**
*
*
* @return
*/
int getCode();
/**
*
*
* @return
*/
String getMessage();
/**
*
*
* @return
*/
ErrorPrefixEnum getCodePrefixEnum();
}

@ -0,0 +1,88 @@
package com.sz.core.common.jackson;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
/**
* Jackson null {@code null}
* <p>
* {@code BeanSerializerModifier} 使 null
* {@code null}
* </p>
*
* <p>
*
* </p>
* <ul>
* <li>String null ""</li>
* <li>List/Set null []</li>
* <li>Map null {}</li>
* <li>Number null 0</li>
* <li>Boolean null false</li>
* </ul>
*
* <p>
* BeanSerializerModifier
*
* <pre>{@code
* if (type.isTypeOrSubTypeOf(String.class)) {
* writer.assignNullSerializer(EmptyStringSerializer.INSTANCE);
* }
* }</pre>
* </p>
*
* @author sz
* @since 2025/7/14
*/
public class EmptySerializer {
public static class EmptyStringSerializer extends JsonSerializer<Object> {
public static final EmptyStringSerializer INSTANCE = new EmptyStringSerializer();
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString("");
}
}
public static class EmptyArraySerializer extends JsonSerializer<Object> {
public static final EmptyArraySerializer INSTANCE = new EmptyArraySerializer();
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartArray();
gen.writeEndArray();
}
}
public static class EmptyObjectSerializer extends JsonSerializer<Object> {
public static final EmptyObjectSerializer INSTANCE = new EmptyObjectSerializer();
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject();
gen.writeEndObject();
}
}
public static class ZeroNumberSerializer extends JsonSerializer<Object> {
public static final ZeroNumberSerializer INSTANCE = new ZeroNumberSerializer();
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeNumber(0);
}
}
public static class FalseBooleanSerializer extends JsonSerializer<Object> {
public static final FalseBooleanSerializer INSTANCE = new FalseBooleanSerializer();
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeBoolean(false);
}
}
}

@ -0,0 +1,44 @@
package com.sz.core.common.jackson;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Jackson "" {@link Map}
* <p>
* {@code Map<?, ?>} {@code ""} Jackson
* {@code new HashMap<>()}
* </p>
*
* <p>
* 使
* </p>
*
* <pre>{@code
*
* @JsonDeserialize(using = EmptyStringAsEmptyMapDeserializer.class)
* private Map<String, Object> extraParams;
* }</pre>
*
* <p>
* 使
* </p>
*
* @author sz
* @since 2025/7/14
*/
public class EmptyStringAsEmptyMapDeserializer extends JsonDeserializer<Map<?, ?>> {
@Override
public Map<?, ?> deserialize(JsonParser parser, DeserializationContext ctx) throws IOException {
if (parser.getCurrentToken().isScalarValue() && "".equals(parser.getText())) {
return new HashMap<>();
}
// 其他情况下走默认处理
return ctx.readValue(parser, Map.class);
}
}

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

Loading…
Cancel
Save