Merge pull request 'master' (#1) from master into main

Reviewed-on: #1
This commit is contained in:
2026-05-08 16:05:32 +08:00
2387 changed files with 261297 additions and 0 deletions

76
.gitignore vendored Normal file
View File

@@ -0,0 +1,76 @@
# For Java
*.lck
target/
*.json
log/
logback-test.xml
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Image snapshot diff
__diff_output__/
/jest-stare
*.iml
.idea/
.ipr
.iws
*~
~*
*.diff
*.patch
*.bak
.DS_Store
Thumbs.db
.project
.*proj
.svn/
*.swp
*.swo
*.log
*.log.*
*.json.gzip
node_modules/
.buildpath
.settings
dist
npm-debug.log
nohup.out
_site
_data
report.html
/lib
/es
elasticsearch-*
config/base.yaml
/.vscode/
/coverage
/.history
*.tmp
!**/nacos/target
**/nacos/data/*
**/nacos/logs/*
**/seata/bin/*

26
Dockerfile Normal file
View File

@@ -0,0 +1,26 @@
# 基础镜像
FROM bellsoft/liberica-openjre-rocky:21
# FROM bellsoft/liberica-openjre-rocky:17
# FROM bellsoft/liberica-openjre-rocky:11
# FROM bellsoft/liberica-openjre-rocky:8
LABEL maintainer=yunzhupaas-team
# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 解决连接SQLServer安全错误
# 如您使用SQLServer数据库把以下注释取消
# COPY security/java.security /opt/java/openjdk/lib/security
# 指定运行时的工作目录
WORKDIR /data/yunzhupaassoft/javaApi
# 将构建产物jar包拷贝到运行时目录中
COPY yunzhupaas-admin/target/*.jar ./yunzhupaas-admin.jar
# 指定容器内运行端口
EXPOSE 30000
# 指定容器启动时要运行的命令
ENTRYPOINT ["/bin/sh","-c","java -Dfile.encoding=utf8 -Djava.security.egd=file:/dev/./urandom -jar yunzhupaas-admin.jar"]

481
README.md Normal file
View File

@@ -0,0 +1,481 @@
> 特别说明源码、JDK、数据库、Redis等安装或存放路径禁止包含中文、空格、特殊字符等
## 一 技术栈
- 编辑语言:`Java8/11``Java17/21`
- 主框架:`Spring Boot 2.7/3.2` + `Spring Framework`
- 持久层框架:`MyBatis-Plus`
- 数据库连接池:`Alibaba Druid`
- 多数据源:`Dynamic-Datasource`
- 数据库兼容: `MySQL`(默认)、`SQLServer``Oracle``PostgreSQL``达数据库``人大金仓数据库`
- 分库分表解决方案:`Apache ShardingSphere`
- 权限认证框架:`Sa-Token`+`JWT`
- 代码生成器:`MyBatis-Plus-Generator`
- 流程引擎:`Flowable 6.7`
- 模板引擎:`Velocity`
- 任务调度:`XXL-JOB`
- 分布式锁:`Lock4j`
- JSON序列化: `Jackson`&`Fastjson`
- 缓存数据库:`Redis`
- 校验框架:`Validation`
- 分布式文件存储:兼容`MinIO`及多个云对象存储,如阿里云 OSS、华为云 OBS、七牛云 Kodo、腾讯云 COS等
- 工具类框架:`Hutool``Lombok`
- 接口文档:`Knife4j`
- 项目构建:`Maven`
## 二 环境要求
### 2.1 开发环境
| 类目 | 版本说明或建议 |
| --- |------------------|
| 硬件 | 开发电脑建议使用I3及以上CPU16G及以上内存 |
| 操作系统 | Windows 10/11MacOS |
| JDK | 默认使用JDK 21如需要切换JDK 8/11/17版本请参考文档调整代码推荐使用 `OpenJDK`,如 `Liberica JDK``Eclipse Temurin``Alibaba Dragonwell``BiSheng` 等发行版; |
| Maven | 依赖管理工具,推荐使用 `3.6.3` 及以上版本 |
| Redis | 数据缓存,推荐使用 `5.0` 及以上版本 |
| 数据库 | 兼容 `MySQL 5.7.x/8.x``SQLServer 2012+``Oracle 11g``PostgreSQL 12+``达梦数据库(DM8)``人大金仓数据库(KingbaseES_V8R6)` |
| IDE | 代码集成开发环境,推荐使用 `IDEA2024` 及以上版本,兼容 `Eclipse``Spring Tool Suite` 等IDE工具 |
| 文件存储 | 默认使用本地存储,兼容 `MinIO` 及多个云对象存储,如 `阿里云 OSS``华为云 OBS``七牛云 Kodo``腾讯云 COS` 等; |
### 2.2 运行环境
> 适用于测试或生产环境
| 类目 | 版本说明或建议 |
| --- |--------------|
| 服务器配置 | 建议至少在 `4C/16G/50G` 的机器配置下运行; |
| 操作系统 | 建议使用 `Windows Server 2019` 及以上版本或主流 `Linux` 发行版本,推荐使用 `Linux` 环境;兼容 `统信UOS``OpenEuler``麒麟服务器版` 等信创环境; |
| JRE | 默认使用JRE 21如需要切换JRE 8/11/17版本请参考文档调整代码推荐使用 `OpenJDK`,如 `Liberica JDK``Eclipse Temurin``Alibaba Dragonwell``BiSheng` 等发行版; |
| Redis | 数据缓存,推荐使用 `5.0` 及以上版本 |
| 数据库 | 兼容 `MySQL 5.7.x/8.x``SQLServer 2012+``Oracle 11g``PostgreSQL 12+``达梦数据库(DM8)``人大金仓数据库(KingbaseES_V8R6)` |
| 中间件(兼容)) | 东方通 `Tong-web`、金蝶天燕-应用服务器`AAS` v10 |
| 文件存储 | 默认使用本地存储,兼容 `MinIO` 及多个云对象存储,如 `阿里云 OSS``华为云 OBS``七牛云 Kodo``腾讯云 COS` 等; |
## 三 IDEA插件
- `Lombok`(必须)
- `Alibaba Java Coding Guidelines`
- `MybatisX`
## 四 Maven私服配置
> 建议使用 Apache Maven 3.6.3 及以上版本<br>以解决依赖无法从公共Maven仓库下载的问题<br>通过官方私服下载依赖完成后由于IDEA的缓存可能会出现部分报红重启IDEA即可
打开Maven安装目录中的 `conf/settings.xml` 文件,<br>
`<servers></servers>` 中添加如下内容
```xml
<server>
<id>maven-releases</id>
<username>admin</username>
<password>admin123</password>
</server>
```
`<mirrors></mirrors>` 中添加
```xml
<mirror>
<id>maven-releases</id>
<mirrorOf>*</mirrorOf>
<name>maven-releases</name>
<url>http://127.0.0.1:7777/repository/maven-public/</url>
</mirror>
```
## 五 配套项目
| 项目 | 分支 | 说明 |
| --- |---------------|-------------------|
| **后端** | | |
| yunzhupaas-common | v5.2.x-stable | java基础依赖项目源码 |
| yunzhupaas-datareport | v5.2.x-stable | 报表后端项目源码 |
| yunzhupaas-file-core-starter | v5.2.x-stable | 文件基础依赖项目源码 |
| yunzhupaas-file-preview | v5.1.xstable | 本地文档预览项目源码 |
| yunzhupaas-java-datareport-univer | v5.2.x-stable | Java Univer报表源码 |
| yunzhupaas-java-datareport-univer-core | v5.2.x-stable | Java Univer报表核心依赖源码不同销售版本交付有所差异具体实际交付为准 |
| yunzhupaas-java-tenant | v5.2.x-stable | 多租户后端源码,不同销售版本交付有所差异,具体实际交付为准 |
| yunzhupaas-scheduletask | v5.2.x-stable | 任务调度客户端依赖及服务端项目源码 |
| yunzhupaas-workflow | v1.0.0-stable | 流程引擎后端项目 |
| yunzhupaas-workflow-core | v1.0.0-stable | Flowable流程引擎基础依赖不同销售版本交付有所差异具体实际交付为准 |
| **前端** | | |
| yunzhupaas-web-datareport | v5.2.x-stable | 报表前端项目源码 |
| yunzhupaas-web-datascreen-vue3 | v5.2.x-stable | 前端大屏项目源码Vue3 |
| yunzhupaas-web-tenant-vue3 | v5.2.x-stable | 多租户前端项目源码Vue3不同销售版本交付有所差异具体实际交付为准 |
| yunzhupaas-web-vue3 | v5.2.x-stable | 前端主项目源码Vue3 |
| **移动端** | | | |
| yunzhupaas-app-vue3 | v5.2.x-stable | 移动端项目源码(Vue3) |
| **静态资源** | | | |
| yunzhupaas-resources | v5.2.x-stable | 静态资源 |
| **数据库** | | |
| yunzhupaas-database | v5.2.x-stable | 数据库脚本或文件 |
## 六 开发环境
### 6.1 导入数据库脚本
> 以 MySQL数据库为例<br>字符集:`utf8mb4` <br/>排序规则:`utf8mb4_general_ci`
#### 6.1.1 创建平台数据库
在MySQL中创建 `yunzhupaas_init` 数据库,并将 `yunzhupaas-database/MySQL/yunzhupaas_db_init.sql` 方式导入。<br/>
若需要使用纯净数据库不含Demo示例则以【新建查询】方式导入 `yunzhupaas_dbnull_init.sql`
若有更新脚本(Update目录下),按日期顺序执行更新
#### 6.1.2 创建系统调度数据库
在MySQL创建 `yunzhupaas_xxjob` 数据库,并将 `yunzhupaas-database/MySQL/yunzhupaas_xxjob_init.sql` 导入;
#### 6.1.3 创建流程数据库
在MySQL创建 `yunzhupaas_flow` 数据库,并将 `yunzhupaas-database/MySQL/yunzhupaas_flow_init.sql` 导入;
### 6.2 导入依赖
#### 6.2.1 基础依赖
详见 `yunzhupaas-common` 项目中的 `README.md` 文档说明
#### 6.2.2 文件基础依赖
详见 `yunzhupaas-file-starter` 项目中的 `README.md` 文档说明
#### 6.2.3 导入系统调度服务端
详见 `yunzhupaas-scheduletask` 项目中的 `README.md` 文档说明
### 6.3 配套项目
#### 6.3.1 yunzhupaas-datareport 报表后端项目
详见 `yunzhupaas-datareport` 项目中的 `README.md` 文档说明
#### 6.3.2 yunzhupaas-java-datareport-univer Java Univer报表后端项目
详见 `yunzhupaas-java-datareport-univer` 项目中的 `README.md` 文档说明
#### 6.3.3 yunzhupaas-workflow 工作流引擎后端项目
详见 `yunzhupaas-workflow` 项目中的 `README.md` 文档说明
### 6.4 项目配置
打开编辑 `yunzhupaas-admin/src/main/resources/application.yml`
#### 6.4.1 指定环境配置
环境说明:
- `application-dev.yml` 开发环境(默认)
- `application-test.yml` 测试环境
- `application-preview.yml` 预发布环境
- `application-prod.yml` 生产环境
> 以开发环境为例,根据实际需求修改
```yaml
# application.yml第6行,可选值dev(开发环境-默认)、test(测试环境)、preview(预生产)、prod(生产环境)
active: dev
```
#### 6.4.2 配置域名
打开编辑 `yunzhupaas-admin/src/main/resources/application.yml` ,修改以下配置
```yaml
PreviewType: kkfile #文件预览方式 1.yozo 2.kkfile默认使用kkfile
kkFileUrl: http://127.0.0.1:30090/FileServer/ #kkfile文件预览服务地址
ApiDomain: http://127.0.0.1:30000 #后端域名(文档预览中使用)
FrontDomain: http://127.0.0.1:3000 #前端域名(文档预览中使用)
AppDomain: http://127.0.0.1:8080 #app/h5端域名配置(文档预览中使用)
FlowDomain: http://127.0.0.1:31000 #流程引擎接口地址
```
#### 6.4.3 数据源配置
配置参数说明:
- `db-type`:数据库类型(可选值:`MySQL``SQLServer``Oracle``PostgreSQL``DM``KingbaseES`
- `host`:数据库主机地址
- `port`:数据库端口
- `dbname`:平台初始库
- `username`:数据库用户名
- `password`:数据库密码
- `db-schema`:数据库模式
- `prepare-url`自定义JDBC连接配置
打开编辑 `yunzhupaas-admin/src/main/resources/application-dev.yml`,修改以下配置
##### 6.4.3.1 MySQL数据库
```yaml
datasource:
db-type: MySQL
host: 127.0.0.1
port: 3306
db-name: yunzhupaas_init
username: dbuser
password: dbpasswd
db-schema:
prepare-url:
```
##### 6.4.3.2 SQLServer数据库
```yaml
datasource:
db-type: SQLServer
host: 127.0.0.1
port: 1433
db-name: yunzhupaas_init
username: dbuser
password: dbpasswd
db-schema:
prepare-url:
```
##### 6.4.3.3 Oracle数据库
```yaml
datasource:
db-type: Oracle
host: 127.0.0.1
port: 1521
db-name:
username: YUNZHUPAAS_INIT
password: dbpasswd
db-schema:
prepare-url: jdbc:oracle:thin:@127.0.0.1:1521:ORCL
```
##### 6.4.3.4 PostgreSQL数据库配置
```yaml
datasource:
db-type: PostgreSQL
host: 127.0.0.1
port: 5432
db-name: yunzhupaas_init
username: dbuser
password: dbpasswd
db-schema: public
prepare-url:
```
##### 6.4.3.5 达梦DM8数据库
```yaml
datasource:
db-type: DM
host: 127.0.0.1
port: 5236
db-name: YUNZHUPAAS_INIT
username: DBUSER
password: dbpasswd
db-schema:
prepare-url:
tablespace: MAIN
```
##### 6.4.3.6 人大金仓KingbaseES_V8R6数据库
```yaml
datasource:
db-type: KingbaseES
host: 127.0.0.1
port: 54321
db-name: yunzhupaas_init
username: dbuser
password: dbpasswd
db-schema:
prepare-url:
```
#### 6.4.4 Redis配置
打开编辑 `yunzhupaas-admin/src/main/resources/application-dev.yml`,修改以下配置
> 支持单机模式和集群模式,配置默认为单机模式
**若使用Redis单机模式**
```yaml
redis:
database: 1 #缓存库编号
host: 127.0.0.1
port: 6379
password: 123456 # 密码为空时,请将本行注释
timeout: 3000 #超时时间(单位:秒)
lettuce: #Lettuce为Redis的Java驱动包
pool:
max-active: 8 # 连接池最大连接数
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
min-idle: 0 # 连接池中的最小空闲连接
max-idle: 8 # 连接池中的最大空闲连接
```
**若使用Redis集群模式**
```yaml
redis:
cluster:
nodes:
- 192.168.0.225:6380
- 192.168.0.225:6381
- 192.168.0.225:6382
- 192.168.0.225:6383
- 192.168.0.225:6384
- 192.168.0.225:6385
password: 123456 # 密码为空时,请将本行注释
timeout: 3000 # 超时时间(单位:秒)
lettuce: #Lettuce为Redis的Java驱动包
pool:
max-active: 8 # 连接池最大连接数
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
min-idle: 0 # 连接池中的最小空闲连接
max-idle: 8 # 连接池中的最大空闲连接
```
#### 6.4.5 静态资源配置
打开编辑 `yunzhupaas-admin/src/main/resources/application-dev.yml` ,修改以下配置
> 默认使用本地存储,兼容 `MinIO` 及多个云对象存储,如阿里云 OSS、华为云 OBS、七牛云 Kodo、腾讯云 COS等
```yaml
# ===================== 文件存储配置 =====================
file-storage: #文件存储配置,不使用的情况下可以不写
default-platform: local-plus-1 #默认使用的存储平台
thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
local-plus: # 本地存储升级版
- platform: local-plus-1 # 存储平台标识
enable-storage: true #启用存储
enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
domain: "" # 访问域名例如“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
base-path: D:/project/yunzhupaas-resources/ # 基础路径
path-patterns: /** # 访问路径
storage-path: # 存储路径
aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
- platform: aliyun-oss-1 # 存储平台标识
enable-storage: false # 启用存储
access-key: ??
secret-key: ??
end-point: ??
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如https://abc.oss-cn-shanghai.aliyuncs.com/
base-path: hy/ # 基础路径
qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
- platform: qiniu-kodo-1 # 存储平台标识
enable-storage: false # 启用存储
access-key: ??
secret-key: ??
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如http://abc.hn-bkt.clouddn.com/
base-path: base/ # 基础路径
tencent-cos: # 腾讯云 COS
- platform: tencent-cos-1 # 存储平台标识
enable-storage: false # 启用存储
secret-id: ??
secret-key: ??
region: ?? #存仓库所在地域
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如https://abc.cos.ap-nanjing.myqcloud.com/
base-path: hy/ # 基础路径
minio: # MinIO由于 MinIO SDK 支持 AWS S3其它兼容 AWS S3 协议的存储平台也都可配置在这里
- platform: minio-1 # 存储平台标识
enable-storage: true # 启用存储
access-key: Q9jJs2b6Tv
secret-key: Thj2WkpLu9DhmJyJ
end-point: http://192.168.0.207:9000/
bucket-name: yunzhupaassoftoss
domain: # 访问域名,注意“/”结尾例如http://minio.abc.com/abc/
base-path: # 基础路径
```
#### 6.4.6 第三方登录配置
打开编辑 `yunzhupaas-admin/src/main/resources/application-dev.yml` ,修改以下配置
> 配置默认关闭
```yaml
socials:
# 第三方登录功能开关(false-关闭true-开启)
socials-enabled: false
config:
- # 微信
provider: wechat_open
client-id: your-client-id
client-secret: your-client-secret
- # qq
provider: qq
client-id: your-client-id
client-secret: your-client-secret
- # 企业微信
provider: wechat_enterprise
client-id: your-client-id
client-secret: your-client-secret
agentId: your-agentId
- # 钉钉
provider: dingtalk
client-id: your-client-id
client-secret: your-client-secret
agentId: your-agentId
- # 飞书
provider: feishu
client-id: your-client-id
client-secret: your-client-secret
- # 小程序
provider: wechat_applets
client-id: your-client-id
client-secret: your-client-secret
```
#### 6.4.7 任务调度配置
打开编辑 `yunzhupaas-admin/src/main/resources/application-dev.yml` ,修改以下配置,调整 xxl.job.admin.addresses 地址
```yaml
xxl:
job:
accessToken: '432e62f3b488bc861d91b0e274e850cc'
i18n: zh_CN
logretentiondays: 30
triggerpool:
fast:
max: 200
slow:
max: 100
# xxl-job服务端地址
admin:
addresses: http://127.0.0.1:30020/xxl-job-admin/
executor:
address: ''
appname: xxl-job-executor-sample1
ip: ''
logpath: /data/applogs/xxl-job/jobhandler
logretentiondays: 30
port: 9999
# rest调用xxl-job接口地址
admin:
register:
handle-query-address: ${xxl.job.admin.addresses}api/handler/queryList
job-info-address: ${xxl.job.admin.addresses}api/jobinfo
log-query-address: ${xxl.job.admin.addresses}api/log
task-list-address: ${xxl.job.admin.addresses}api/ScheduleTask/List
task-info-address: ${xxl.job.admin.addresses}api/ScheduleTask/getInfo
task-save-address: ${xxl.job.admin.addresses}api/ScheduleTask
task-update-address: ${xxl.job.admin.addresses}api/ScheduleTask
task-remove-address: ${xxl.job.admin.addresses}api/ScheduleTask/remove
task-start-or-remove-address: ${xxl.job.admin.addresses}api/ScheduleTask/updateTask
```
## 七 启动项目
找到`yunzhupaas-admin/src/main/java/YunzhupaasAdminApplication.java`,右击运行即可。
## 八 项目发布
- 在IDEA中双击右侧Maven中 `yunzhupaas-java-boot` > `Lifecycle` > `clean` 清理项目
- 在IDEA中双击右侧Maven中 `yunzhupaas-java-boot` > `Lifecycle` > `package` 打包项目
- 打开 `yunzhupaas-java-boot\yunzhupaas-admin\target`,将 `yunzhupaas-admin-5.2.0-RELEASE.jar` 上传至服务器
## 九 接口文档
- `http://localhost:30000/doc.html`

55
pom.xml Normal file
View File

@@ -0,0 +1,55 @@
<?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">
<parent>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-common</artifactId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-java-boot</artifactId>
<packaging>pom</packaging>
<version>5.2.0-RELEASE</version>
<modules>
<module>yunzhupaas-admin</module>
<module>yunzhupaas-oauth</module>
<module>yunzhupaas-system</module>
<module>yunzhupaas-public/yunzhupaas-common-all</module>
<module>yunzhupaas-example</module>
<module>yunzhupaas-extend</module>
<module>yunzhupaas-visualdev</module>
<!-- <module>yunzhupaas-workflow</module>-->
<module>yunzhupaas-file</module>
<module>yunzhupaas-exception</module>
<module>yunzhupaas-visualdata</module>
<module>yunzhupaas-app</module>
<module>yunzhupaas-permission</module>
<module>yunzhupaas-scheduletask</module>
<module>yunzhupaas-message</module>
<module>yunzhupaas-public/yunzhupaas-provider</module>
<module>yunzhupaas-public/yunzhupaas-generater-base</module>
<module>yunzhupaas-flowable</module>
<module>yunzhupaas-train</module>
<module>yunzhupaas-mdm</module>
<module>yunzhupaas-crm</module>
<module>yunzhupaas-pcm</module>
</modules>
<properties>
</properties>
<dependencyManagement>
<dependencies>
</dependencies>
</dependencyManagement>
</project>

1304
security/java.security Normal file

File diff suppressed because it is too large Load Diff

205
yunzhupaas-admin/pom.xml Normal file
View File

@@ -0,0 +1,205 @@
<?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">
<parent>
<artifactId>yunzhupaas-java-boot</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-admin</artifactId>
<packaging>jar</packaging>
<!--打包WAR包删除注释-->
<!--<packaging>war</packaging>-->
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-file-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-extend-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-system-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-scheduletask-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-message-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-permission-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-visualdev-base-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-visualdev-onlinedev-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-visualdev-generater-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-visualdev-portal-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-visualdata-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-exception</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-oauth-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-example-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-app-controller</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 基础信息-->
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-mdm-controller</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 客户关系-->
<!-- <dependency>-->
<!-- <groupId>com.yunzhupaas</groupId>-->
<!-- <artifactId>yunzhupaas-crm-controller</artifactId>-->
<!-- <version>${project.version}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.yunzhupaas</groupId>-->
<!-- <artifactId>yunzhupaas-pcm-controller</artifactId>-->
<!-- <version>${project.version}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-visualdev-integrate-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-flowable-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-train-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-common-i18n</artifactId>
</dependency>
<!-- 单点登录相关依赖-Start -->
<!-- <dependency>-->
<!-- <groupId>com.yunzhupaas</groupId>-->
<!-- <artifactId>yunzhupaas-sso-starter-all</artifactId>-->
<!-- <version>${project.version}</version>-->
<!-- </dependency>-->
<!-- 单点登录(用户信息拉取)相关依赖 -->
<!-- <dependency>-->
<!-- <groupId>com.yunzhupaas</groupId>-->
<!-- <artifactId>yunzhupaas-sso-connector</artifactId>-->
<!-- <version>${project.version}</version>-->
<!-- </dependency>-->
<!-- 单点登录(用户信息推送)相关依赖 -->
<!-- <dependency>-->
<!-- <groupId>com.yunzhupaas</groupId>-->
<!-- <artifactId>yunzhupaas-sso-pull</artifactId>-->
<!-- <version>${project.version}</version>-->
<!-- </dependency>-->
<!-- 单点登录相关依赖-End -->
<!--打包WAR包删除注释-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- ... -->
<!--打包WAR包注释插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.yunzhupaas.AdminApplication</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- ... -->
<!--打包WAR包删除注释-->
<!--<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<warSourceExcludes>src/main/resources/**</warSourceExcludes>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>-->
</plugins>
</build>
</project>

View File

@@ -0,0 +1,28 @@
package com.yunzhupaas;
import cn.xuyanwu.spring.file.storage.EnableFileStorage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/**
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/15 17:12
*/
@SpringBootApplication(scanBasePackages = { "com.yunzhupaas" }, exclude = { DataSourceAutoConfiguration.class })
@EnableFileStorage
public class AdminApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(AdminApplication.class);
// 添加监听器
// springApplication.addListeners(new YunzhupaasListener());
springApplication.run(args);
System.out.println("YunzhuPaasAdmin启动完成");
}
}

View File

@@ -0,0 +1,88 @@
package com.yunzhupaas.aop;
import cn.dev33.satoken.context.SaHolder;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.config.ConfigValueUtil;
import com.yunzhupaas.database.util.NotTenantPluginHolder;
import com.yunzhupaas.database.util.TenantDataSourceUtil;
import com.yunzhupaas.util.TenantHolder;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.UserProvider;
import com.yunzhupaas.util.data.DataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/15 17:12
*/
@Slf4j
@Aspect
@Component
@Order(1)
public class DataSourceBindAspect {
@Autowired
private ConfigValueUtil configValueUtil;
@Pointcut("within(com.yunzhupaas.*.controller.* || com.yunzhupaas.controller.*)")
public void bindDataSource() {
}
/**
* NoDataSourceBind 不需要绑定数据库的注解
*
* @param pjp
* @return
* @throws Throwable
*/
@Around("bindDataSource() && !@annotation(com.yunzhupaas.util.NoDataSourceBind)")
public Object doAroundService(ProceedingJoinPoint pjp) throws Throwable {
// System.out.println(SaHolder.getRequest().getRequestPath());
if (configValueUtil.isMultiTenancy()) {
if(StringUtil.isEmpty(TenantHolder.getDatasourceId())){
UserInfo userInfo = UserProvider.getUser();
String url = null;
try{
url = SaHolder.getRequest().getRequestPath();
}catch (Exception ee){ }
log.error("租户" + userInfo.getTenantId() + "数据库不存在, URL: {}, TOKEN: {}", url, userInfo.getToken());
return null;
}
return pjp.proceed();
}
Object obj = pjp.proceed();
return obj;
}
/**
* NoDataSourceBind 不需要绑定数据库的注解 加入不切租户库标记
*
* @param pjp
* @return
* @throws Throwable
*/
@Around("bindDataSource() && @annotation(com.yunzhupaas.util.NoDataSourceBind)")
public Object doAroundService2(ProceedingJoinPoint pjp) throws Throwable {
try{
NotTenantPluginHolder.setNotSwitchAlwaysFlag();
//Filter中提前设置租户信息, 不需要切库的方法进行清除切库
TenantDataSourceUtil.clearLocalTenantInfo();
return pjp.proceed();
}finally {
NotTenantPluginHolder.clearNotSwitchAlwaysFlag();
}
}
}

View File

@@ -0,0 +1,77 @@
package com.yunzhupaas.aop;
import cn.xuyanwu.spring.file.storage.FileInfo;
import cn.xuyanwu.spring.file.storage.UploadPretreatment;
import cn.xuyanwu.spring.file.storage.aspect.*;
import cn.xuyanwu.spring.file.storage.platform.FileStorage;
import cn.xuyanwu.spring.file.storage.recorder.FileRecorder;
import com.yunzhupaas.config.ConfigValueUtil;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.util.PdfUtil;
import com.yunzhupaas.util.XSSEscape;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.util.function.Consumer;
@Slf4j
@Component
public class MyFileAspect implements FileStorageAspect {
@Autowired
private ConfigValueUtil configValueUtil;
@Override
public FileInfo uploadAround(UploadAspectChain chain, FileInfo fileInfo, UploadPretreatment pre, FileStorage fileStorage, FileRecorder fileRecorder) {
checkFilePath(fileInfo);
if(configValueUtil.isCheckFilePdf()) {
try {
String ext = fileInfo.getExt();
if("pdf".equalsIgnoreCase(ext)) {
log.error("检测PDF文件");
if (PdfUtil.containsJavaScript(pre.getFileWrapper().getBytes())) {
throw new DataException(MsgCode.FA053.get());
}
}
} catch (IOException e) {
log.error("PDF文档解析失败: {}", e.getMessage());
}
}
return FileStorageAspect.super.uploadAround(chain, fileInfo, pre, fileStorage, fileRecorder);
}
@Override
public boolean deleteAround(DeleteAspectChain chain, FileInfo fileInfo, FileStorage fileStorage, FileRecorder fileRecorder) {
checkFilePath(fileInfo);
return FileStorageAspect.super.deleteAround(chain, fileInfo, fileStorage, fileRecorder);
}
@Override
public boolean existsAround(ExistsAspectChain chain, FileInfo fileInfo, FileStorage fileStorage) {
checkFilePath(fileInfo);
return FileStorageAspect.super.existsAround(chain, fileInfo, fileStorage);
}
@Override
public void downloadAround(DownloadAspectChain chain, FileInfo fileInfo, FileStorage fileStorage, Consumer<InputStream> consumer) {
checkFilePath(fileInfo);
FileStorageAspect.super.downloadAround(chain, fileInfo, fileStorage, consumer);
}
@Override
public void downloadThAround(DownloadThAspectChain chain, FileInfo fileInfo, FileStorage fileStorage, Consumer<InputStream> consumer) {
checkFilePath(fileInfo);
FileStorageAspect.super.downloadThAround(chain, fileInfo, fileStorage, consumer);
}
private void checkFilePath(FileInfo fileInfo){
//处理特殊文件名
fileInfo.setPath(XSSEscape.escapePath(fileInfo.getPath()));
fileInfo.setFilename(XSSEscape.escapePath(fileInfo.getFilename()));
}
}

View File

@@ -0,0 +1,69 @@
package com.yunzhupaas.aop;
import com.yunzhupaas.constant.PermissionConstant;
import com.yunzhupaas.permission.entity.OrganizeRelationEntity;
import com.yunzhupaas.permission.model.authorize.SaveBatchForm;
import com.yunzhupaas.permission.service.OrganizeRelationService;
import com.yunzhupaas.util.PermissionAspectUtil;
import com.yunzhupaas.util.UserProvider;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/15 17:12
*/
@Slf4j
@Aspect
@Component
public class PermissionAdminAspect implements PermissionAdminBase{
/**
* 分级管理切点
*/
@Pointcut("within(com.yunzhupaas.*.controller.*) && @annotation(com.yunzhupaas.annotation.OrganizeAdminIsTrator)")
public void pointcut() {
}
/**
* 分级管理切点
*
* @param pjp
* @return
* @throws Throwable
*/
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
return PermissionAdminBase.permissionCommon(pjp, this);
}
@Override
public Boolean detailPermission(ProceedingJoinPoint pjp, String operatorUserId, String methodName){
switch (methodName) {
case PermissionConstant.METHOD_SAVE:
case PermissionConstant.METHOD_SAVE_BATCH:
return true;
case PermissionConstant.METHOD_UPDATE:
//判断是否有当前组织的修改权限
String organizeId = String.valueOf(pjp.getArgs()[0]);
return PermissionAspectUtil.containPermission(organizeId, operatorUserId, methodName);
default:
return false;
}
}
}

View File

@@ -0,0 +1,40 @@
package com.yunzhupaas.aop;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.util.UserProvider;
import org.aspectj.lang.ProceedingJoinPoint;
public interface PermissionAdminBase{
/**
* 详细的权限判断
* @param pjp AOP切点参数
* @param operatorUserId 操作者对象
*/
Boolean detailPermission(ProceedingJoinPoint pjp, String operatorUserId, String methodName);
/**
* 管理者权限判断
*
*/
static Object permissionCommon(ProceedingJoinPoint pjp, PermissionAdminBase permissionAdminBase) throws Throwable {
// 获取用户信息
UserInfo operatorUser = UserProvider.getUser();
// 是否是管理员
if(operatorUser.getIsAdministrator()){
return pjp.proceed();
}else {
// 获取方法名
String methodName = pjp.getSignature().getName();
// 具体方法权限
if(permissionAdminBase.detailPermission(pjp, operatorUser.getUserId(),methodName)){
return pjp.proceed();
}
}
return ActionResult.fail(MsgCode.FA021.get());
}
}

View File

@@ -0,0 +1,120 @@
package com.yunzhupaas.aop;
import com.yunzhupaas.constant.PermissionConstant;
import com.yunzhupaas.permission.entity.OrganizeEntity;
import com.yunzhupaas.permission.model.organize.OrganizeCrForm;
import com.yunzhupaas.permission.model.organize.OrganizeDepartCrForm;
import com.yunzhupaas.permission.model.organize.OrganizeDepartUpForm;
import com.yunzhupaas.permission.model.organize.OrganizeUpForm;
import com.yunzhupaas.permission.service.OrganizeService;
import com.yunzhupaas.util.PermissionAspectUtil;
import com.yunzhupaas.util.UserProvider;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.StringJoiner;
/**
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/15 17:12
*/
@Slf4j
@Aspect
@Component
public class PermissionOrgAspect implements PermissionAdminBase {
@Autowired
private OrganizeService organizeService;
/**
* 分级管理切点
*/
@Pointcut("within(com.yunzhupaas.*.controller.*) && @annotation(com.yunzhupaas.annotation.OrganizePermission)")
public void pointcut() {
}
/**
* 分级管理切点
*
* @param pjp
* @return
* @throws Throwable
*/
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
return PermissionAdminBase.permissionCommon(pjp, this);
}
@Override
public Boolean detailPermission(ProceedingJoinPoint pjp, String operatorUserId, String methodName) {
switch (methodName) {
case PermissionConstant.METHOD_CREATE:
return PermissionAspectUtil.getPermitByOrgIds(
// 操作目标对象表单对象
((OrganizeCrForm) pjp.getArgs()[0]).getParentId(),
operatorUserId,
PermissionConstant.METHOD_CREATE);
case PermissionConstant.METHOD_CREATE_DEPARTMENT:
return PermissionAspectUtil.getPermitByOrgIds(
// 操作目标对象表单对象
((OrganizeDepartCrForm) pjp.getArgs()[0]).getParentId(),
operatorUserId,
PermissionConstant.METHOD_CREATE);
case PermissionConstant.METHOD_UPDATE:
// 当前组织id
String orgId = (String) pjp.getArgs()[0];
// 当前组织父级id
OrganizeEntity info = organizeService.getInfo(orgId);
// 修改后的id
OrganizeUpForm organizeUpForm = (OrganizeUpForm) pjp.getArgs()[1];
StringJoiner stringJoiner = new StringJoiner(",");
stringJoiner.add(orgId);
if (!organizeUpForm.getParentId().equals(info.getParentId()) && !"-1".equals(info.getParentId())) {
stringJoiner.add(info.getParentId());
}
if (!organizeUpForm.getParentId().equals(info.getParentId()) && !"-1".equals(organizeUpForm.getParentId())) {
stringJoiner.add(organizeUpForm.getParentId());
}
return PermissionAspectUtil.getPermitByOrgIds(
// 操作目标对象ID
stringJoiner.toString(),
operatorUserId,
PermissionConstant.METHOD_UPDATE);
case PermissionConstant.METHOD_UPDATE_DEPARTMENT:
// 当前组织id
String orgIds = (String) pjp.getArgs()[0];
// 当前组织父级id
OrganizeEntity infos = organizeService.getInfo(orgIds);
// 修改后的id
OrganizeDepartUpForm organizeDepartUpForm = (OrganizeDepartUpForm) pjp.getArgs()[1];
StringJoiner stringJoiners = new StringJoiner(",");
stringJoiners.add(orgIds);
if (!organizeDepartUpForm.getParentId().equals(infos.getParentId())) {
stringJoiners.add(infos.getParentId());
stringJoiners.add(organizeDepartUpForm.getParentId());
}
return PermissionAspectUtil.getPermitByOrgIds(
// 操作目标对象ID
stringJoiners.toString(),
operatorUserId,
PermissionConstant.METHOD_UPDATE);
case PermissionConstant.METHOD_DELETE:
case PermissionConstant.METHOD_DELETE_DEPARTMENT:
return PermissionAspectUtil.getPermitByOrgIds(
// 操作目标对象ID
pjp.getArgs()[0].toString(),
operatorUserId,
PermissionConstant.METHOD_DELETE);
default:
return false;
}
}
}

View File

@@ -0,0 +1,92 @@
package com.yunzhupaas.aop;
import com.yunzhupaas.constant.PermissionConstant;
import com.yunzhupaas.permission.entity.PositionEntity;
import com.yunzhupaas.permission.model.position.PositionCrForm;
import com.yunzhupaas.permission.model.position.PositionUpForm;
import com.yunzhupaas.permission.service.OrganizeService;
import com.yunzhupaas.permission.service.PositionService;
import com.yunzhupaas.util.PermissionAspectUtil;
import com.yunzhupaas.util.UserProvider;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/15 17:12
*/
@Slf4j
@Aspect
@Component
public class PermissionPositionAspect implements PermissionAdminBase{
@Autowired
private PositionService positionService;
@Autowired
private OrganizeService organizeService;
/**
* 分级管理切点
*/
@Pointcut("within(com.yunzhupaas.*.controller.*) && @annotation(com.yunzhupaas.annotation.PositionPermission)")
public void pointcut() {
}
/**
* 分级管理切点
*
* @param pjp
* @return
* @throws Throwable
*/
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
return PermissionAdminBase.permissionCommon(pjp, this);
}
@Override
public Boolean detailPermission(ProceedingJoinPoint pjp, String operatorUserId, String methodName) {
switch (methodName){
case PermissionConstant.METHOD_CREATE:
return PermissionAspectUtil.getPermitByOrgId(
// 操作目标对象组织ID集合
((PositionCrForm) pjp.getArgs()[0]).getOrganizeId(),
operatorUserId,
methodName);
case PermissionConstant.METHOD_UPDATE:
// 得到岗位信息后,判断是否有修改前的权限
PositionEntity info = positionService.getInfo(((String) pjp.getArgs()[0]));
if (PermissionAspectUtil.getPermitByOrgId(
// 操作目标对象组织ID集合
info.getOrganizeId(),
operatorUserId,
methodName)) {
return PermissionAspectUtil.getPermitByOrgId(
// 操作目标对象组织ID集合
((PositionUpForm) pjp.getArgs()[1]).getOrganizeId(),
operatorUserId,
methodName);
}
return false;
case PermissionConstant.METHOD_DELETE:
// 获取岗位所关联的组织ID字符串
String positionId = String.valueOf(pjp.getArgs()[0]);
String orgIds = organizeService.getInfo(positionService.getInfo(positionId).getOrganizeId()).getId();
return PermissionAspectUtil.getPermitByOrgId(
// 操作目标对象组织ID集合
orgIds,
operatorUserId,
PermissionConstant.METHOD_DELETE);
default:
return false;
}
}
}

View File

@@ -0,0 +1,153 @@
package com.yunzhupaas.aop;
import com.yunzhupaas.constant.PermissionConstant;
import com.yunzhupaas.permission.entity.OrganizeRelationEntity;
import com.yunzhupaas.permission.entity.RoleEntity;
import com.yunzhupaas.permission.model.role.RoleCrForm;
import com.yunzhupaas.permission.model.role.RoleUpForm;
import com.yunzhupaas.permission.service.OrganizeRelationService;
import com.yunzhupaas.permission.service.PositionService;
import com.yunzhupaas.permission.service.RoleService;
import com.yunzhupaas.util.PermissionAspectUtil;
import com.yunzhupaas.util.UserProvider;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;
/**
* 角色操作权限
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/2/10
*/
@Slf4j
@Aspect
@Component
public class PermissionRoleAspect implements PermissionAdminBase {
@Autowired
private RoleService roleService;
@Autowired
private OrganizeRelationService organizeRelationService;
/**
* 分级管理切点
*/
@Pointcut("within(com.yunzhupaas.*.controller.*) && @annotation(com.yunzhupaas.annotation.RolePermission)")
public void pointcut() {
}
/**
* 分级管理切点
*
* @param pjp
* @return
* @throws Throwable
*/
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
return PermissionAdminBase.permissionCommon(pjp, this);
}
@Override
public Boolean detailPermission(ProceedingJoinPoint pjp, String operatorUserId, String methodName) {
boolean flag = false;
switch (methodName) {
case PermissionConstant.METHOD_CREATE:
RoleCrForm roleCrForm = (RoleCrForm) pjp.getArgs()[0];
if (!checkAdminGlobal(roleCrForm.getGlobalMark())) {
return PermissionAspectUtil.getPermitByOrgId(
// 操作目标对象组织ID集合
getOrganize(roleCrForm.getOrganizeIdsTree()),
operatorUserId,
PermissionConstant.METHOD_CREATE);
}
return true;
case PermissionConstant.METHOD_UPDATE:
RoleUpForm roleUpForm = (RoleUpForm) pjp.getArgs()[0];
// 非管理员情况下
if (!checkAdminGlobal(roleUpForm.getGlobalMark())) {
// 得到以前的组织id
String roleId = (String) pjp.getArgs()[1];
List<String> relationListByRoleId = organizeRelationService.getRelationListByRoleId(roleId).stream().map(OrganizeRelationEntity::getOrganizeId).collect(Collectors.toList());
StringJoiner stringJoiners = new StringJoiner(",");
relationListByRoleId.forEach(t -> {
stringJoiners.add(t);
});
if (PermissionAspectUtil.getPermitByOrgId(
// 操作目标对象组织ID集合
stringJoiners.toString(),
operatorUserId,
PermissionConstant.METHOD_UPDATE)) {
return PermissionAspectUtil.getPermitByOrgId(
// 操作目标对象组织ID集合
getOrganize(roleUpForm.getOrganizeIdsTree()),
operatorUserId,
PermissionConstant.METHOD_UPDATE);
}
return false;
}
return true;
case PermissionConstant.METHOD_DELETE:
String roleId = pjp.getArgs()[0].toString();
RoleEntity roleEntity = roleService.getInfo(roleId);
// 获取角色关联的组织信息
List<OrganizeRelationEntity> relationListByRoleId = organizeRelationService.getRelationListByRoleId(roleId);
StringBuilder orgId = new StringBuilder();
relationListByRoleId.stream().forEach(t->{
orgId.append(t.getOrganizeId() + ",");
});
if (roleEntity != null && !checkAdminGlobal(roleEntity.getGlobalMark())) {
return PermissionAspectUtil.getPermitByOrgId(
// 操作目标对象组织ID集合
orgId.toString(),
operatorUserId,
PermissionConstant.METHOD_DELETE);
}
return true;
default:
break;
}
return true;
}
/**
* 转成组织id字符串
* @param orgIdsTree
* @return
*/
private String getOrganize(List<List<String>> orgIdsTree) {
StringBuilder orgIds = new StringBuilder();
for (List<String> list : orgIdsTree) {
if (list.size() > 0) {
String orgId = list.get(list.size() - 1);
orgIds.append(orgId + ",");
}
}
return orgIds.toString();
}
/**
* 全局角色只能超管来操作
*
* @param globalMark 全局标识 1全局 0: 非全局
*/
private Boolean checkAdminGlobal(Integer globalMark) {
if (globalMark != null && globalMark == 1) {
return UserProvider.getUser().getIsAdministrator();
}
return false;
}
}

View File

@@ -0,0 +1,150 @@
package com.yunzhupaas.aop;
import com.yunzhupaas.constant.PermissionConst;
import com.yunzhupaas.constant.PermissionConstant;
import com.yunzhupaas.permission.entity.OrganizeRelationEntity;
import com.yunzhupaas.permission.entity.UserRelationEntity;
import com.yunzhupaas.permission.model.user.form.UserCrForm;
import com.yunzhupaas.permission.model.user.form.UserUpForm;
import com.yunzhupaas.permission.model.userrelation.UserRelationForm;
import com.yunzhupaas.permission.service.*;
import com.yunzhupaas.util.PermissionAspectUtil;
import com.yunzhupaas.util.UserProvider;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;
/**
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/15 17:12
*/
@Slf4j
@Aspect
@Component
public class PermissionUserAspect implements PermissionAdminBase{
@Autowired
private OrganizeRelationService organizeRelationService;
@Autowired
private PositionService positionService;
@Autowired
private UserRelationService userRelationService;
/**
* 分级管理切点
*/
@Pointcut("within(com.yunzhupaas.*.controller.*) && @annotation(com.yunzhupaas.annotation.UserPermission)")
public void pointcut() {
}
/**
* 分级管理切点
*
* @param pjp
* @return
* @throws Throwable
*/
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
return PermissionAdminBase.permissionCommon(pjp, this);
}
@Override
public Boolean detailPermission(ProceedingJoinPoint pjp, String operatorUserId, String methodName) {
switch (methodName){
case PermissionConstant.METHOD_CREATE:
UserCrForm userCrForm = (UserCrForm) pjp.getArgs()[0];
return PermissionAspectUtil.getPermitByOrgId(
// 操作目标对象组织ID集合
userCrForm.getOrganizeId(),
operatorUserId,
PermissionConstant.METHOD_CREATE);
case PermissionConstant.METHOD_UPDATE:
// 得到修改的用户以前的信息
String userId = (String) pjp.getArgs()[0];
List<String> collect = userRelationService.getListByUserId(userId, PermissionConst.ORGANIZE).stream().map(UserRelationEntity::getObjectId).collect(Collectors.toList());
StringJoiner stringJoiner = new StringJoiner(",");
collect.forEach(t -> {
stringJoiner.add(t);
});
if (PermissionAspectUtil.getPermitByOrgId(
// 操作目标对象组织ID集合
stringJoiner.toString(),
operatorUserId,
PermissionConstant.METHOD_UPDATE)) {
return PermissionAspectUtil.getPermitByOrgId(
// 操作目标对象组织ID集合
((UserUpForm) pjp.getArgs()[1]).getOrganizeId(),
operatorUserId,
PermissionConstant.METHOD_UPDATE);
}
return false;
case PermissionConstant.METHOD_MODIFY_PW:
return PermissionAspectUtil.getPermitByUserId(
// 操作目标对象的ID
String.valueOf(pjp.getArgs()[0]),
operatorUserId,
PermissionConstant.METHOD_UPDATE);
case PermissionConstant.METHOD_DELETE:
return PermissionAspectUtil.getPermitByUserId(
// 操作目标对象的ID
pjp.getArgs()[0].toString(),
operatorUserId,
PermissionConstant.METHOD_DELETE);
case PermissionConstant.METHOD_SAVE:
String objId = pjp.getArgs()[0].toString();
UserRelationForm userRelationForm = (UserRelationForm)pjp.getArgs()[1];
List<String> orgIds = new ArrayList<>();
if(userRelationForm.getObjectType().equals(PermissionConst.ROLE)){
// 角色目前修改为只有超管才能够修改
if(UserProvider.getUser().getIsAdministrator()){
return true;
}
orgIds.addAll(organizeRelationService.getRelationListByRoleId(objId).stream().map(OrganizeRelationEntity::getOrganizeId).collect(Collectors.toList()));
return PermissionAspectUtil.getPermitByOrgId(
// 操作目标对象组织ID集合
String.join(",", orgIds),
operatorUserId,
PermissionConstant.METHOD_UPDATE);
}else {
if(userRelationForm.getObjectType().equals(PermissionConst.GROUP)) {
return true;
}
if(userRelationForm.getObjectType().equals(PermissionConst.POSITION)) {
orgIds.add(positionService.getInfo(objId).getOrganizeId());
}
return PermissionAspectUtil.getPermitByOrgId(
String.join(",", orgIds),
operatorUserId,
PermissionConstant.METHOD_UPDATE);
}
case PermissionConstant.METHOD_DELETE_SOCIALS:
if(pjp.getArgs()[0].toString().equals(operatorUserId)){return true;}
return PermissionAspectUtil.getPermitByUserId(
// 操作目标对象的ID
pjp.getArgs()[0].toString(),
operatorUserId,
PermissionConstant.METHOD_UPDATE);
default:
return false;
}
}
}

View File

@@ -0,0 +1,239 @@
package com.yunzhupaas.aop;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.yunzhupaas.base.LogSortEnum;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.config.ConfigValueUtil;
import com.yunzhupaas.entity.LogEntity;
import com.yunzhupaas.service.LogService;
import com.yunzhupaas.util.*;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.yunzhupaas.annotation.HandleLog;
import org.springframework.web.multipart.MultipartFile;
import java.lang.reflect.Method;
import java.util.Date;
/**
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/15 17:12
*/
@Slf4j
@Aspect
@Component
@Order(2)
public class RequestLogAspect {
@Autowired
private ConfigValueUtil configValueUtil;
@Autowired
private LogService logService;
@Pointcut("within(com.yunzhupaas.*.controller.* || com.yunzhupaas.controller.*)")// && !within(com.yunzhupaas.controller.UtilsController)
public void requestLog() {
}
@Around("requestLog()")
public Object doAroundService(ProceedingJoinPoint pjp) throws Throwable {
long startTime = System.currentTimeMillis();
Object obj = pjp.proceed();
if(ServletUtil.getRequest() == null){
return obj;
}
long costTime = System.currentTimeMillis() - startTime;
UserInfo userInfo = UserProvider.getUser();
if(userInfo.getUserId() != null && (!configValueUtil.isMultiTenancy() || TenantHolder.getLocalTenantCache() != null)) {
// 得到请求参数
Object[] args = pjp.getArgs();
Signature signature = pjp.getSignature();
printLog(userInfo, costTime, obj, args, signature);
try {
// 判断是否需要操作日志
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
// 得到请求方法
Method method = methodSignature.getMethod();
HandleLog methodAnnotation = method.getAnnotation(HandleLog.class);
if (methodAnnotation != null) {
String moduleName = methodAnnotation.moduleName();
String requestMethod = methodAnnotation.requestMethod();
handleLog(userInfo, costTime, obj, moduleName, requestMethod, args, signature);
}
} catch (Exception e) {
log.error("记录操作日志发生错误:" + e.getMessage());
}
}
return obj;
}
/**
* 请求日志
*
* @param userInfo
* @param costTime
*/
private void printLog(UserInfo userInfo, long costTime, Object obj, Object[] args, Signature signature) {
LogEntity entity = new LogEntity();
entity.setId(RandomUtil.uuId());
entity.setType(LogSortEnum.Request.getCode());
entity.setUserId(userInfo.getUserId());
entity.setUserName(userInfo.getUserName() + "/" + userInfo.getUserAccount());
//请求耗时
entity.setRequestDuration((int) costTime);
entity.setRequestUrl(ServletUtil.getRequest().getServletPath());
entity.setRequestMethod(ServletUtil.getRequest().getMethod());
String ipAddr = IpUtil.getIpAddr();
entity.setIpAddress(ipAddr);
entity.setIpAddressName(IpUtil.getIpCity(ipAddr));
entity.setCreatorTime(new Date());
UserAgent userAgent = UserAgentUtil.parse(ServletUtil.getUserAgent());
if (userAgent != null) {
entity.setPlatForm(userAgent.getPlatform().getName() + " " + userAgent.getOsVersion());
entity.setBrowser(userAgent.getBrowser().getName() + " " + userAgent.getVersion());
}
String declaringTypeName = signature.getDeclaringTypeName();
String name = signature.getName();
entity.setRequestTarget(declaringTypeName + "." + name);
entity.setJsons(obj + "");
StringBuilder stringBuilder = new StringBuilder();
for (Object o : args) {
// 如果是MultipartFile则为导入
if (o instanceof MultipartFile) {
stringBuilder.append("{\"originalFilename\":\"" + ((MultipartFile) o).getOriginalFilename() + "\",");
stringBuilder.append("\"contentType\":\"" + ((MultipartFile) o).getContentType() + "\",");
stringBuilder.append("\"name\":\"" + ((MultipartFile) o).getName() + "\",");
stringBuilder.append("\"resource\":\"" + ((MultipartFile) o).getResource() + "\",");
stringBuilder.append("\"size\":\"" + ((MultipartFile) o).getSize() + "\"}");
}
}
if (stringBuilder.length() > 0) {
entity.setRequestParam(stringBuilder.toString());
} else {
entity.setRequestParam(JsonUtil.getObjectToString(args));
}
ThreadPoolExecutorUtil.getExecutor().execute(()->{
logService.save(entity);
});
}
/**
* 添加操作日志
*
* @param userInfo 用户信息
* @param costTime 操作耗时
* @param obj 请求结果
* @param moduleName 模块名称
* @param requestMethod 请求方法
* @param args 请求参数
*/
private void handleLog(UserInfo userInfo, long costTime, Object obj, String moduleName, String requestMethod, Object[] args, Signature signature) {
LogEntity entity = new LogEntity();
entity.setId(RandomUtil.uuId());
entity.setType(LogSortEnum.Operate.getCode());
entity.setUserId(userInfo.getUserId());
entity.setUserName(userInfo.getUserName() + "/" + userInfo.getUserAccount());
//请求耗时
entity.setRequestDuration((int) costTime);
entity.setRequestMethod(ServletUtil.getRequest().getMethod());
entity.setRequestUrl(ServletUtil.getRequest().getServletPath());
String ipAddr = IpUtil.getIpAddr();
entity.setIpAddress(ipAddr);
entity.setIpAddressName(IpUtil.getIpCity(ipAddr));
entity.setCreatorTime(new Date());
// 请求设备
UserAgent userAgent = UserAgentUtil.parse(ServletUtil.getUserAgent());
if (userAgent != null) {
entity.setPlatForm(userAgent.getPlatform().getName() + " " + userAgent.getOsVersion());
entity.setBrowser(userAgent.getBrowser().getName() + " " + userAgent.getVersion());
}
// 操作模块
entity.setModuleName(moduleName);
String declaringTypeName = signature.getDeclaringTypeName();
String name = signature.getName();
entity.setRequestTarget(declaringTypeName + "." + name);
// 操作记录
StringBuilder stringBuilder = new StringBuilder();
for (Object o : args) {
// 如果是MultipartFile则为导入
if (o instanceof MultipartFile) {
stringBuilder.append("{\"originalFilename\":\"" + ((MultipartFile) o).getOriginalFilename() + "\",");
stringBuilder.append("\"contentType\":\"" + ((MultipartFile) o).getContentType() + "\",");
stringBuilder.append("\"name\":\"" + ((MultipartFile) o).getName() + "\",");
stringBuilder.append("\"resource\":\"" + ((MultipartFile) o).getResource() + "\",");
stringBuilder.append("\"size\":\"" + ((MultipartFile) o).getSize() + "\"}");
}
}
if (stringBuilder.length() > 0) {
entity.setRequestParam(stringBuilder.toString());
} else {
entity.setRequestParam(JsonUtil.getObjectToString(args));
}
entity.setJsons(obj + "");
ThreadPoolExecutorUtil.getExecutor().execute(()->{
logService.save(entity);
});
}
/// 后面可能会用
// /**
// * 判断是否为导入导出
// *
// * @return
// */
// private String getRequestMethod() {
// //得到请求方式
// String methodType = ServletUtil.getRequest().getMethod();
// // 得到当前请求的尾缀
// String endWith = null;
// String servletPath = ServletUtil.getServletPath();
// if (StringUtil.isNotEmpty(servletPath)) {
// String[] path = servletPath.split("/");
// int length = path.length;
// if (length > 5) {
// endWith = path[length - 2] + "/" + path[length - 1];
// }
// }
// // 如果是GET请求且请求后缀是'/Action/Export'则判定为导出
// if (HandleMethodEnum.GET.getRequestType().equals(methodType)) {
// methodType = "Action/Export".equals(endWith) ? "EXPORT" : "GET";
// } else if (HandleMethodEnum.POST.getRequestType().equals(methodType)) {
// methodType = "Action/Import".equals(endWith) ? "IMPORT" : "GET";
// }
// return methodType;
// }
// /**
// * 判断是否为导入导出
// *
// * @return
// */
// private String getRequestModuleName() {
// //得到Url
// String requestURI = ServletUtil.getRequest().getRequestURI();
// // 取模块名
// if (StringUtil.isNotEmpty(requestURI)) {
// String[] split = requestURI.split("/");
// if (split.length > 2) {
// String url = split[1];
// // 得到所在模块
// String moduleName = HandleModuleEnum.getModuleByURL(url);
// return moduleName;
// }
// }
// return "";
// }
///
}

View File

@@ -0,0 +1,47 @@
package com.yunzhupaas.aop;
import com.yunzhupaas.util.RedisUtil;
import com.yunzhupaas.util.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.Set;
/**
* 可视化开发缓存数据处理
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/15 17:12
*/
@Slf4j
//@Aspect
//@Component
public class VisiualOpaAspect {
@Autowired
private RedisUtil redisUtil;
@Pointcut("(execution(* com.yunzhupaas.onlinedev.controller.VisualdevModelDataController.*(..))) || execution(* com.yunzhupaas.onlinedev.controller.VisualdevModelAppController.*(..)))" +
"|| execution(* com.yunzhupaas.generater.controller.VisualdevGenController.*(..)))")
public void visiualOpa() {
}
@After("visiualOpa()")
public void doAroundService(){
String method=ServletUtil.getRequest().getMethod().toLowerCase();
if("put".equals(method)||"delete".equals(method)||"post".equals(method)){
Set<String> allKey=new HashSet<>(16);
allKey.addAll(redisUtil.getAllVisiualKeys());
for(String key:allKey){
redisUtil.remove(key);
}
}
}
}

View File

@@ -0,0 +1,74 @@
package com.yunzhupaas.constant;
/**
* 分级管理常量
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司http://www.szlecheng.cn
* @date 2024-11-01
*/
public class PermissionConstant {
/**
* 创建方法
*/
public static final String METHOD_CREATE = "create";
/**
* 编辑方法
*/
public static final String METHOD_UPDATE = "update";
/**
* 删除方法
*/
public static final String METHOD_DELETE = "delete";
/**
* 更新状态
*/
public static final String METHOD_DISABLE = "disable";
/**
* 创建方法
*/
public static final String METHOD_CREATE_DEPARTMENT = "createDepartment";
/**
* 编辑方法
*/
public static final String METHOD_UPDATE_DEPARTMENT = "updateDepartment";
/**
* 删除方法
*/
public static final String METHOD_DELETE_DEPARTMENT = "deleteDepartment";
/**
* 保存方法
*/
public static final String METHOD_SAVE = "save";
public static final String METHOD_SAVE_BATCH = "saveBatch";
/**
* 修改用户密码
*/
public static final String METHOD_MODIFY_PW = "modifyPassword";
/**
* 拼接方法名
*/
public static final String GET_METHOD_CREATE = "Add";
public static final String GET_METHOD_UPDATE = "Edit";
public static final String GET_METHOD_DELETE = "Delete";
public static final String GET_METHOD_SELECT = "Select";
public static final String GET_METHOD_THIS = "getThisLayer";
public static final String GET_METHOD_SUB = "getSubLayer";
/**
* 解除绑定方法
*/
public static final String METHOD_DELETE_SOCIALS = "deleteSocials";
}

View File

@@ -0,0 +1,102 @@
package com.yunzhupaas.filter;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.filter.SaFilterAuthStrategy;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.yunzhupaas.base.ActionResultCode;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.consts.AuthConsts;
import com.yunzhupaas.properties.GatewayWhite;
import com.yunzhupaas.util.IpUtil;
import com.yunzhupaas.util.UserProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 网关验证token
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司http://www.szlecheng.cn
* @date 2024-03-24
*/
@Slf4j
@Configuration
public class AuthFilter {
@Autowired
private GatewayWhite gatewayWhite;
@Autowired
private SaFilterAuthStrategy defaultBeforeAuthStrategy;
// 注册 Sa-Token全局过滤器
@Bean
public SaServletFilter getSaReactorFilter() {
return new SaServletFilter()
// 拦截地址
.addInclude("/**")
.setExcludeList(gatewayWhite.excludeUrl)
// 鉴权方法:每次访问进入
.setAuth(obj -> {
if(log.isInfoEnabled()){
log.info("请求路径: {}", SaHolder.getRequest().getRequestPath());
}
//拦截路径
SaRouter.match(gatewayWhite.blockUrl).match(o -> {
//禁止访问URL 排除白名单
String ip = getIpAddr();
for (String o1 : gatewayWhite.whiteIp) {
if(ip.startsWith(o1)){
return false;
}
}
log.info("非白名单IP访问限制接口{}, {}", SaHolder.getRequest().getRequestPath(), ip);
return true;
}).back(MsgCode.AD101.get());
//测试不验证 鉴权服务重启测试模式不清除Token就够了
//SaRouter.match((r)->"true".equals(configValueUtil.getTestVersion())).stop();
//白名单不拦截
SaRouter.match(gatewayWhite.whiteUrl).stop();
//内部请求不拦截
SaRouter.match(t->{
String innerToken = SaHolder.getRequest().getHeader(AuthConsts.INNER_TOKEN_KEY);
return UserProvider.isValidInnerToken(innerToken);
}).stop();
// 登录校验 -- 校验多租户管理模块TOKEN
//SaRouter.match("/api/tenant/**", r -> {
// SaManager.getStpLogic(AuthConsts.ACCOUNT_TYPE_TENANT).checkLogin();
//}).stop();
// 登录校验 -- 拦截所有路由
SaRouter.match("/**", r -> {
StpUtil.checkLogin();
}).stop();
}).setError(e -> {
SaHolder.getResponse().addHeader("Content-Type","application/json; charset=utf-8");
if(e instanceof NotLoginException){
return SaResult.error(ActionResultCode.SessionOverdue.getMessage()).setCode(ActionResultCode.SessionOverdue.getCode());
}
log.error(e.getMessage(), e);
return SaResult.error(MsgCode.AD102.get()).setCode(ActionResultCode.Exception.getCode());
})
// 前置函数:在每次认证函数之前执行
.setBeforeAuth(defaultBeforeAuthStrategy);
}
public static String getIpAddr() {
return IpUtil.getIpAddr();
}
}

View File

@@ -0,0 +1,114 @@
package com.yunzhupaas.filter;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.filter.SaFilterAuthStrategy;
import cn.dev33.satoken.router.SaRouter;
import com.yunzhupaas.properties.MvcSecurityProperties;
import com.yunzhupaas.util.Constants;
import com.yunzhupaas.util.IpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.util.ObjectUtils;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.net.URI;
/**
* mvc配置
*
* @author 云筑产品开发平台组
* @version V5.2.0
* @copyright 深圳市乐程软件有限公司http://www.szlecheng.cn
* @date 2025-01-21
*/
@Slf4j
@Configuration(proxyBeanMethods = false)
public class MvcSecurityConfig {
private static final String DOMAIN_FORMAT = "%s://%s";
@Autowired
private MvcSecurityProperties mvcSecurityProperties;
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
// 允许发送凭据
config.setAllowCredentials(true);
//允许任意域名跨域访问接口
config.setAllowedOrigins(mvcSecurityProperties.getCors().getAllowedOrigins());
config.setAllowedOriginPatterns(mvcSecurityProperties.getCors().getAllowedOriginPatterns());
// 允许所有头部信息
config.setAllowedHeaders(mvcSecurityProperties.getCors().getAllowedHeaders());
// 允许所有请求方法
config.setAllowedMethods(mvcSecurityProperties.getCors().getAllowedMethods());
// 应用于所有路径
source.registerCorsConfiguration("/**", config);
return new MyCorsFilter(source);
}
@Bean
@ConditionalOnMissingBean
public SaFilterAuthStrategy defaultBeforeAuthStrategy() {
CorsConfiguration csrfConfiguration;
if(!mvcSecurityProperties.getCsrfOrigins().isEmpty() || !mvcSecurityProperties.getCsrfOriginsPatterns().isEmpty()) {
csrfConfiguration = new CorsConfiguration();
csrfConfiguration.setAllowedOrigins(mvcSecurityProperties.getCsrfOrigins());
csrfConfiguration.setAllowedOriginPatterns(mvcSecurityProperties.getCsrfOriginsPatterns());
} else {
csrfConfiguration = null;
}
return obj -> {
SaRequest request = SaHolder.getRequest();
// ---------- 设置跨域响应头 ----------
SaResponse response = SaHolder.getResponse();
if(!ObjectUtils.isEmpty(mvcSecurityProperties.getHeaders().getServerName())){
response.setServer(mvcSecurityProperties.getHeaders().getServerName());
}
if(!ObjectUtils.isEmpty(mvcSecurityProperties.getHeaders().getXFrameOptions()) && !MvcSecurityProperties.XFrameOptionsMode.DISABLED.equals(mvcSecurityProperties.getHeaders().getXFrameOptions())){
response.setHeader(MvcSecurityProperties.HEADER_XFRAME_OPTIONS, mvcSecurityProperties.getHeaders().getXFrameOptions().getMode());
}
if(!ObjectUtils.isEmpty(mvcSecurityProperties.getHeaders().getXXssProtection()) && !MvcSecurityProperties.XXssProtectionMode.DISABLED.equals(mvcSecurityProperties.getHeaders().getXXssProtection())){
response.setHeader(MvcSecurityProperties.HEADER_XSS_PROTECTION, mvcSecurityProperties.getHeaders().getXXssProtection().getMode());
}
if(!ObjectUtils.isEmpty(mvcSecurityProperties.getHeaders().getXContentTypeOptions()) && !MvcSecurityProperties.XContentTypeOptions.DISABLED.equals(mvcSecurityProperties.getHeaders().getXContentTypeOptions())){
response.setHeader(MvcSecurityProperties.HEADER_Content_Type_Options, mvcSecurityProperties.getHeaders().getXContentTypeOptions().getMode());
}
if(csrfConfiguration != null){
String referer = request.getHeader("referer");
if(!ObjectUtils.isEmpty(referer)) {
URI uri = URI.create(referer);
String refererDomain = String.format(DOMAIN_FORMAT, uri.getScheme(), uri.getAuthority());
String allowOrign = csrfConfiguration.checkOrigin(refererDomain);
if(ObjectUtils.isEmpty(allowOrign)){
log.error("Reject CSRF Request: {}, {}, {}, {}", request.getRequestPath(), referer, IpUtil.getIpAddr(), request.getHeader(Constants.AUTHORIZATION));
response.setStatus(HttpStatus.FORBIDDEN.value());
SaRouter.back("Invalid CSRF Request");
}
}
}
};
}
@Order(-110)
public static class MyCorsFilter extends CorsFilter {
public MyCorsFilter(CorsConfigurationSource configSource) {
super(configSource);
}
}
}

View File

@@ -0,0 +1,166 @@
package com.yunzhupaas.util;
import com.yunzhupaas.constant.PermissionConstant;
import com.yunzhupaas.permission.entity.OrganizeAdministratorEntity;
import com.yunzhupaas.permission.entity.OrganizeEntity;
import com.yunzhupaas.permission.service.OrganizeAdministratorService;
import com.yunzhupaas.permission.service.OrganizeService;
import com.yunzhupaas.util.context.SpringContext;
/**
* 分级管理工具类
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司http://www.szlecheng.cn
* @date 2024-11-01
*/
public class PermissionAspectUtil {
private static final OrganizeService organizeService;
private static final OrganizeAdministratorService organizeAdministratorService;
static {
organizeService = SpringContext.getBean(OrganizeService.class);
organizeAdministratorService = SpringContext.getBean(OrganizeAdministratorService.class);
}
/**
* 判断是否存在修改前所在的组织的操作
*
* @param targetUserId 被操作目标对象ID
* @param operatorUsrId 操作者ID
* @param methodName 操作方法
*/
public static Boolean getPermitByUserId(String targetUserId, String operatorUsrId, String methodName) {
for(OrganizeEntity organizeEntity : organizeService.getAllOrgByUserId(targetUserId)){
if (PermissionAspectUtil.containPermission(organizeEntity.getId(), operatorUsrId, methodName)) {
return true;
}
}
return false;
}
/**
* 判断 操作者是否含有该组织的操作权限
*
* @param organizeId 被操作者所在组织ID
* @param operatorUserId 当前操作者用户对象ID
* @param methodName 操作类型:创建、编辑、删除
*/
public static boolean containPermission(String organizeId, String operatorUserId, String methodName) {
OrganizeEntity organizeEntity = organizeService.getInfo(organizeId);
if (organizeEntity != null) {
// 当前用户的所有分级权限
OrganizeAdministratorEntity adminEntity = organizeAdministratorService.getOne(operatorUserId, organizeId);
if(permissionFlag(adminEntity, methodName, true)){
return true;
}
// 查看父级的组织权限是否含有子集权限
return parentPermission(organizeEntity.getParentId(), methodName, operatorUserId);
}
return false;
}
/**
* 判断是否存在修改前所在的组织的操作(拥有所有的组织权限才能操作)
*
* @param organizeIds 组织ID集合字符串
* @param operatorUsrId 操作者ID
* @param methodName 操作方法
*/
public static Boolean getPermitByOrgIds(String organizeIds, String operatorUsrId, String methodName) {
boolean flag = true;
for (String organizeId : organizeIds.split(",")) {
flag = true;
flag = PermissionAspectUtil.containPermission(organizeId, operatorUsrId, methodName);
if (!flag) {
break;
}
}
return flag;
}
/**
* 判断是否可修改所在的组织的操作(只要有一个权限即可操作)
*
* @param organizeIds 组织ID集合字符串
* @param operatorUsrId 操作者ID
* @param methodName 操作方法
*/
public static Boolean getPermitByOrgId(String organizeIds, String operatorUsrId, String methodName) {
for (String organizeId : organizeIds.split(",")) {
if (PermissionAspectUtil.containPermission(organizeId,operatorUsrId, methodName)) {
return true;
}
}
return false;
}
/**
* 判断组织新建权限(从父级给的子集新建操作权限)
*
* @param organizeParentId
* @param methodName
* @param userId
* @return
*/
private static boolean parentPermission(String organizeParentId, String methodName, String userId) {
// 得到父级组织
OrganizeEntity parentOrganizeEntity = organizeService.getInfo(organizeParentId);
if (parentOrganizeEntity != null) {
// 得到父级的权限
if(permissionFlag(organizeAdministratorService.getOne(userId, parentOrganizeEntity.getId()), methodName, false)){
return true;
}
// 当前正在判断的组织已经是顶级则无需递归
if (!"-1".equals(parentOrganizeEntity.getParentId())) {
return parentPermission(parentOrganizeEntity.getParentId(), methodName, userId);
}
}
return false;
}
/**
* 判断是否具有权限
* @param adminEntity 分级管理对象
* @param methodName 操作类型:创建、编辑、删除
* @param thisFlag true:当前组织 false:子组织
*/
private static boolean permissionFlag(OrganizeAdministratorEntity adminEntity, String methodName, Boolean thisFlag) {
if (adminEntity != null) {
String methodType = "";
// 存在则验证是否有当前组织分级管理
try {
switch (methodName) {
case PermissionConstant.METHOD_CREATE:
// 创建权限
methodType = PermissionConstant.GET_METHOD_CREATE;
break;
case PermissionConstant.METHOD_UPDATE:
// 编辑权限
methodType = PermissionConstant.GET_METHOD_UPDATE;
break;
case PermissionConstant.METHOD_DELETE:
// 删除权限
methodType = PermissionConstant.GET_METHOD_DELETE;
break;
default:
break;
}
// 拼接方法名
String method = (thisFlag ? PermissionConstant.GET_METHOD_THIS : PermissionConstant.GET_METHOD_SUB) + methodType;
String selectMethod = (thisFlag ? PermissionConstant.GET_METHOD_THIS : PermissionConstant.GET_METHOD_SUB) + PermissionConstant.GET_METHOD_SELECT;
if ((int)OrganizeAdministratorEntity.class.getMethod(method).invoke(adminEntity) == 1 && (int)OrganizeAdministratorEntity.class.getMethod(selectMethod).invoke(adminEntity) == 1) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
}

View File

@@ -0,0 +1,34 @@
# General
error.size.toolarge=\u8F93\u5165\u592A\u5927\u3002\u5B9E\u9645\u7684\u8F93\u5165\u4E3A{0}\u5B57\u8282\u3002\u5141\u8BB8\u7684\u6700\u5927\u8F93\u5165\u4E3A{1}\u5B57\u8282\u3002
error.comment.removed=\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u6CE8\u91CA\u57DF\u5DF2\u88AB\u8FC7\u6EE4\u3002\u6CE8\u91CA\u57DF\u7684\u503C\u4E3A{0}
# Tag related
error.tag.notfound=\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u6807\u8BB0{0}\u5DF2\u88AB\u8FC7\u6EE4\u3002\u6807\u8BB0\u7684\u5185\u5BB9\u4FDD\u5B58\u4E0D\u53D8\u3002
error.tag.removed=\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u6807\u8BB0{0}\u4E0D\u88AB\u5141\u8BB8\u3002\u6B64\u6807\u8BB0\u4E0D\u5E94\u8BE5\u5F71\u54CD\u8F93\u5165\u7684\u663E\u793A\u3002
error.tag.filtered=\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u6807\u8BB0{0}\u5DF2\u88AB\u8FC7\u6EE4\u3002\u6807\u8BB0\u7684\u5185\u5BB9\u4FDD\u5B58\u4E0D\u53D8\u3002
error.tag.encoded=The {0} tag has been encoded for security reasons. The contents of the tag will remain in place.
error.tag.empty=\u5728{0}\u7684\u6807\u7B7E\u662F\u7A7A\u7684\uFF0C\u56E0\u6B64\u6211\u4EEC\u65E0\u6CD5\u5904\u7406\u5B83\u3002\u8BE5\u90AE\u4EF6\u7684\u5176\u4F59\u90E8\u5206\u662F\u5B8C\u6574\u7684\uFF0C\u5176\u642C\u8FC1\u5E94\u8BE5\u6CA1\u6709\u4EFB\u4F55\u526F\u4F5C\u7528\u3002
error.cdata.found=\u4E00\u4E2ACDATA\u90E8\u5206\u88AB\u53D1\u73B0\uFF0C\u8FD9\u662F\u4E0D\u5141\u8BB8\u7684\u3002\u8BE5\u90AE\u4EF6\u7684\u5176\u4F59\u90E8\u5206\u662F\u5B8C\u6574\u7684\uFF0C\u5176\u642C\u8FC1\u4E0D\u5E94\u8BE5\u6709\u4EFB\u4F55\u526F\u4F5C\u7528\u3002\u5728CDATA\u7684\u5185\u5BB9\u662F \"{0}\"\u3002
error.pi.found=XML\u5904\u7406\u6307\u4EE4\u88AB\u53D1\u73B0\uFF0C\u8FD9\u662F\u4E0D\u5141\u8BB8\u7684\u3002\u6D88\u606F\u7684\u5176\u4F59\u90E8\u5206\u662F\u5B8C\u6574\u7684\uFF0C\u5176\u642C\u8FC1\u5E94\u8BE5\u4E0D\u4F1A\u6709\u4EFB\u4F55\u526F\u4F5C\u7528\u3002\u8BE5\u6307\u4EE4\u7684\u5185\u5BB9\u4E3A \"{0}\"\u3002
# Attribute related
error.attribute.notfound=\u6807\u8BB0{0}\u5305\u542B\u4E00\u4E2A\u6CA1\u6CD5\u5904\u7406\u7684\u5C5E\u6027\u3002\u5C5E\u6027{1}\u5DF2\u88AB\u8FC7\u6EE4\uFF0C\u4F46\u6807\u8BB0\u4FDD\u5B58\u4E0D\u53D8\u3002
error.attribute.invalid=\u6807\u8BB0{0}\u5305\u542B\u4E00\u4E2A\u6CA1\u6CD5\u5904\u7406\u7684\u5C5E\u6027\u3002\u5C5E\u6027{1}\u5305\u542B\u4E00\u4E2A\u503C\"{2}\"\u3002\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u8FD9\u4E2A\u503C\u6CA1\u6CD5\u88AB\u63A5\u53D7\u3002\u4E3A\u4E86\u5904\u7406\u8FD9\u4E2A\u8F93\u5165\uFF0C\u8FD9\u4E2A\u5C5E\u6027\u5DF2\u88AB\u4ECE\u8FD9\u4E2A\u6807\u8BB0\u4E2D\u53BB\u6389\uFF0C\u6807\u8BB0\u5176\u4ED6\u90E8\u5206\u4FDD\u6301\u4E0D\u53D8\u3002
error.attribute.invalid.filtered=\u6807\u8BB0{0}\u5305\u542B\u4E00\u4E2A\u6CA1\u6CD5\u5904\u7406\u7684\u5C5E\u3002\u5C5E\u6027{1}\u5305\u542B\u4E00\u4E2A\u503C\"{2}\"\u3002\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u8FD9\u4E2A\u503C\u6CA1\u6CD5\u88AB\u63A5\u53D7\u3002\u4E3A\u4E86\u8FDB\u4E00\u6B65\u5904\u7406\u8FD9\u4E2A\u8F93\u5165\uFF0C\u6807\u8BB0{0}\u5DF2\u88AB\u8FC7\u6EE4\u3002
error.attribute.invalid.encoded=The {0} tag contained an attribute that we could not process. The {1} attribute had a value of \"{2}\". This value could not be accepted for security reasons. We have chosen to encode the {0} tag in order to continue processing the input.
error.attribute.invalid.removed=\u6807\u8BB0{0}\u5305\u542B\u4E00\u4E2A\u6CA1\u6CD5\u5904\u7406\u7684\u5C5E\u6027\u3002\u5C5E\u6027{1}\u5305\u542B\u4E00\u4E2A\u503C\"{2}\"\u3002\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u8FD9\u4E2A\u503C\u6CA1\u6CD5\u88AB\u63A5\u53D7\u3002\u4E3A\u4E86\u8FDB\u4E00\u6B65\u5904\u7406\u8FD9\u4E2A\u8F93\u5165\uFF0C\u6574\u4E2A\u6807\u8BB0{0}\u5DF2\u88AB\u53BB\u6389\u3002
# CSS related
error.css.tag.malformed=The stylesheet code \"{0}\" could not be parsed.
error.css.import.disabled=\u6837\u5F0F\u8868\u7684\u5BFC\u5165\u8FD8\u6CA1\u6709\u88AB\u6FC0\u6D3B\u3002
error.css.import.exceeded=\u4F4D\u4E8E{0}\u7684\u6837\u5F0F\u8868\u8D85\u8FC7\u5141\u8BB8\u5BFC\u5165\u7684\u6837\u5F0F\u8868\u7684\u603B\u6570\uFF0C\u56E0\u6B64\u8BE5\u6837\u5F0F\u8868\u6CA1\u6709\u88AB\u8BFB\u53D6\u3002\u5141\u8BB8\u5BFC\u5165\u7684\u6837\u5F0F\u8868\u7684\u6700\u5927\u6570\u76EE\u4E3A{1}\u3002
error.css.import.failure=\u8F93\u5165\u4E2D\u542B\u6709\u7684\u8FDC\u7A0B\u6837\u5F0F\u8868\u4F4D\u4E8E{0}\uFF0C\u6B64\u6837\u5F0F\u8868\u6CA1\u6CD5\u88AB\u8BFB\u53D6\u3002\u7F51\u7AD9\u53EF\u80FD\u5173\u95ED\u6216\u8005\u4E3B\u673A\u6CA1\u6CD5\u88AB\u8BBF\u95EE\u3002\u8FD9\u4E0D\u5E94\u8BE5\u5F71\u54CD\u8F93\u5165\u7684\u683C\u5F0F\u3002
error.css.import.toolarge=\u4F4D\u4E8E{0}\u7684\u6837\u5F0F\u8868\u4F7F\u5F97\u603B\u8F93\u5165\u592A\u5927\uFF0C\u56E0\u6B64\u6CA1\u6709\u88AB\u5BFC\u5165\u3002\u5141\u8BB8\u7684\u6700\u5927\u8F93\u5165\u4E3A{1}\u5B57\u8282\u3002
error.css.import.url.invalid=\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u7528\u4E8E\u5BFC\u5165\u6837\u5F0F\u8868\u7684url\u6CA1\u6CD5\u88AB\u63A5\u53D7\u3002\u6B64url\u662F{1}\u3002
error.css.stylesheet.relative=\u6837\u5F0F\u8868\u5F15\u7528\u4E86\u4E00\u4E2A\u6CA1\u6CD5\u8BFB\u53D6\u7684\u76F8\u5BF9\u6837\u5F0F\u8868\"{0}\"\u3002
error.css.tag.relative=\u6807\u8BB0{0}\u4E2D\u7684\u4E00\u4E2A\u6837\u5F0F\u5C5E\u6027\u6307\u5B9A\u4E86\u4E00\u4E2A\u6CA1\u6CD5\u8BFB\u53D6\u7684\u76F8\u5BF9\u6837\u5F0F\u8868\u5E94\u7528\"{0}\"\u3002
error.css.stylesheet.rule.notfound=\u6837\u5F0F\u8868\u4F7F\u7528\u4E86\u4E00\u4E2A\u4E0D\u88AB\u652F\u6301\u7684\u89C4\u5219\"{0}\"\u3002\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u6B64\u89C4\u5219\u5DF2\u88AB\u53BB\u6389\u3002
error.css.tag.rule.notfound=\u6807\u8BB0{0}\u4E2D\u7684\u4E00\u4E2A\u6837\u5F0F\u5C5E\u6027\u4F7F\u7528\u4E86\u4E00\u4E2A\u4E0D\u88AB\u652F\u6301\u7684\u89C4\u5219\"{0}\"\u3002\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u6B64\u89C4\u5219\u5DF2\u88AB\u53BB\u6389\u3002
error.css.stylesheet.selector.notfound=\u6837\u5F0F\u8868\u4F7F\u7528\u4E86\u4E00\u4E2A\u6CA1\u6CD5\u5904\u7406\u7684\u9009\u62E9\u5668\"{0}\"\u3002\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u6B64\u9009\u62E9\u5668\u5DF2\u88AB\u53BB\u6389\u3002
error.css.tag.selector.notfound=\u6807\u8BB0{0}\u4E2D\u7684\u4E00\u4E2A\u6837\u5F0F\u5C5E\u6027\u4F7F\u7528\u4E86\u4E00\u4E2A\u6CA1\u6CD5\u5904\u7406\u7684\u9009\u62E9\u5668\"{0}\"\u3002\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u6B64\u89C4\u5219\u5DF2\u88AB\u53BB\u6389\u3002
error.css.stylesheet.selector.disallowed=\u6837\u5F0F\u8868\u4F7F\u7528\u4E86\u4E00\u4E2A\u9009\u62E9\u5668\"{0}\"\u3002\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u6B64\u9009\u62E9\u5668\u4E0D\u88AB\u5141\u8BB8\u3002
error.css.tag.selector.disallowed=\u6807\u8BB0{0}\u4E2D\u7684\u4E00\u4E2A\u6837\u5F0F\u5C5E\u6027\u4F7F\u7528\u4E86\u4E00\u4E2A\u9009\u62E9\u5668\"{1}\"\u3002\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u6B64\u9009\u62E9\u5668\u4E0D\u88AB\u5141\u8BB8\u3002
error.css.stylesheet.property.invalid=\u6837\u5F0F\u8868\u542B\u6709\u4E00\u4E2A\u5C5E\uFF08property)\"{0}\"\u3002\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u6B64\u5C5E\u6027\u4E0D\u88AB\u5141\u8BB8\u3002
error.css.tag.property.invalid=\u6807\u8BB0{0}\u4E2D\u542B\u6709\u4E00\u4E2A\u6837\u5F0F\u5C5E\u6027\"{1}\"\u3002\u51FA\u4E8E\u5B89\u5168\u7684\u539F\u56E0\uFF0C\u6B64\u5C5E\u6027\u4E0D\u88AB\u5141\u8BB8\u3002

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!--
W3C rules retrieved from:
http://www.w3.org/TR/html401/struct/global.html
-->
<anti-samy-rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="antisamy.xsd">
<directives>
<directive name="omitXmlDeclaration" value="true"/>
<directive name="omitDoctypeDeclaration" value="true"/>
<directive name="maxInputSize" value="0"/>
<directive name="useXHTML" value="true"/>
<directive name="formatOutput" value="false"/>
<!--
remember, this won't work for relative URIs - AntiSamy doesn't
know anything about the URL or your web structure
-->
<directive name="embedStyleSheets" value="false"/>
</directives>
<common-regexps>
</common-regexps>
<!--
Tag.name = a, b, div, body, etc.
Tag.action = filter: remove tags, but keep content, validate: keep content as long as it passes rules, remove: remove tag and contents
Attribute.name = id, class, href, align, width, etc.
Attribute.onInvalid = what to do when the attribute is invalid, e.g., remove the tag (removeTag), remove the attribute (removeAttribute), filter the tag (filterTag)
Attribute.description = What rules in English you want to tell the users they can have for this attribute. Include helpful things so they'll be able to tune their HTML
-->
<!--
Some attributes are common to all (or most) HTML tags. There aren't many that qualify for this. You have to make sure there's no
collisions between any of these attribute names with attribute names of other tags that are for different purposes.
-->
<common-attributes>
</common-attributes>
<!--
This requires normal updates as browsers continue to diverge from the W3C and each other. As long as the browser wars continue
this is going to continue. I'm not sure war is the right word for what's going on. Doesn't somebody have to win a war after
a while? Even wars of attrition, surely?
-->
<global-tag-attributes>
</global-tag-attributes>
<tags-to-encode>
</tags-to-encode>
<tag-rules>
</tag-rules>
<!-- CSS validation processing rules -->
<css-rules>
<!-- end manual properties -->
</css-rules>
<allowed-empty-tags>
</allowed-empty-tags>
</anti-samy-rules>

View File

@@ -0,0 +1,370 @@
# 应用服务器
server:
tomcat:
uri-encoding: UTF-8 #tomcat编码
port: 40000 #tomcat端口
spring:
messages:
basename: i18n/message
# 一天刷新一次
cache-duration: 24H
devtools: #spring开发者工具模块
restart:
enabled: true #热部署开关
freemarker:
cache: false #spring内置freemarker缓存
thymeleaf:
cache: false #spring内置thymeleaf缓存
# ===================== 数据源配置 =====================
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure #排除自动配置手动配置druid
datasource:
db-type: MySQL #数据库类型(可选值 MySQL、SQLServer、Oracle、DM8、KingbaseES、PostgreSQL请严格按可选值填写)
# host: aliyun.szlecheng.cn
host: mysql.szlecheng.cn
port: 13306
username: jnpfsoft
password: ZtRmzjij4CiaXpSE
db-name: jnpfsoft_dev
db-schema: #金仓达梦选填
prepare-url: #自定义url
# ===================== 动态多数据源 =====================
dynamic:
primary: master #设置默认的数据源或者数据源组,默认值即为master
strict: true #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
druid:
# 空闲时执行连接测试
test-while-idle: true
# 连接测试最小间隔
time-between-eviction-runs-millis: 60000
# 获取连接等待3秒 根据网络情况设定
max-wait: 3000
# 初始化4个连接
initial-size: 4
# 最大20个连接
max-active: 20
# 最少保持4个空闲连接
min-idle: 4
# 空闲连接保活, 超过配置的空闲时间会进行连接检查完成保活操作(数据库自身会断开达到空闲时间的连接, 程序使用断开的连接会报错)
keep-alive: true
# 连接超时
connect-timeout: 10000
# 连接超时
socket-timeout: 10000
# 查询超时
query-timeout: 90000
# 事务查询超时
transaction-query-timeout: 90000
# 解除注释后Druid连接池打印SQL语句 忽略日志等级配置
# filters: slf4j
slf4j:
statementLogEnabled: true
resultSetLogEnabled: false
connectionLogEnabled: false
dataSourceLogEnabled: false
statementCreateAfterLogEnabled: false
statementCloseAfterLogEnabled: false
statementExecuteAfterLogEnabled: false
#打印SQL替换参数
statementExecutableSqlLogEnable: true
statementPrepareAfterLogEnabled: false
statementPrepareCallAfterLogEnabled: false
statementParameterSetLogEnabled: false
# datasource:
# master:
# url: jdbc:mysql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.dbname}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
# username: ${spring.datasource.username}
# password: ${spring.datasource.password}
# driver-class-name: com.mysql.cj.jdbc.Driver
# ===================== Redis配置 =====================
# redis单机模式
data:
redis:
database: 10
host: 127.0.0.1
port: 6379
# password: redis_JtjYRD # 密码为空时,请将本行注释
timeout: 3000 #超时时间(单位:秒)
lettuce: #Lettuce为Redis的Java驱动包
pool:
max-active: 8 # 连接池最大连接数
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
min-idle: 0 # 连接池中的最小空闲连接
max-idle: 8 # 连接池中的最大空闲连接
# redis集群模式
# redis:
# cluster:
# nodes:
# - 192.168.0.225:6380
# - 192.168.0.225:6381
# - 192.168.0.225:6382
# - 192.168.0.225:6383
# - 192.168.0.225:6384
# - 192.168.0.225:6385
# password: 123456 # 密码为空时,请将本行注释
# timeout: 3000 # 超时时间(单位:秒)
# lettuce: #Lettuce为Redis的Java驱动包
# pool:
# max-active: 8 # 连接池最大连接数
# max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
# min-idle: 0 # 连接池中的最小空闲连接
# max-idle: 8 # 连接池中的最大空闲连接
# ===================== Redis配置-End =====================
# ===================== 单点登录(用户信息同步)配置-Start =====================
cloud:
stream:
# 若使用RocketMQ-Start
rocketmq:
binder:
name-server: 192.168.10.6:30094
group: maxkey_identity
# 若使用RocketMQ-End
# 若使用RabbitMQ-Start
# binders:
# defaultRabbit: # 表示定义的名称用于binding整合
# type: rabbit # 消息组件类型
# environment: # 设置rabbitmq的相关环境配置
# spring:
# rabbitmq:
# host: 192.168.10.6
# port: 5672
# username: rabbitmq
# password: rabbitmq
# 若使用RabbitMQ-End
# 若使用Kafka-Start
# kafka:
# # KafkaBinderConfigurationProperties
# binder:
# brokers: 192.168.10.6:9092
# 若使用Kafka-End
bindings:
ssoEventReceiver-in-0:
content-type: text/json
destination: MXK_IDENTITY_MAIN_TOPIC
group: maxkey_identity
# ===================== 单点登录(用户信息同步)配置-End =====================
# ===================== AI配置-Start =====================
ai:
openai:
enabled: true
# 超时时间, 秒, 根据AI平台性能调整超时时间
timeout: 300
# 阿里百联平台
api-host: https://dashscope.aliyuncs.com/compatible-mode/
api-key: sk-def0e6d9d0f8497cb5bcfff8c0c19935
chat:
mode: qwen-max
# GPT转发平台
# api-host: https://api.chatanywhere.tech/
# api-key:
# chat:
# mode: gpt-3.5-turbo
# DeepSeek
# api-host: https://api.deepseek.com/v1/
# api-key:
# chat:
# mode: deepseek-chat
# ===================== AI配置-End =====================
# SpringDoc接口文档 访问地址http://127.0.0.1:30000/doc.html
springdoc:
default-flat-param-object: true
api-docs:
enabled: true
#SpringDoc增强
#knife4j:
# enable: true
# basic: #接口文档访问鉴权
# enable: true
# username: yunzhupaas
# password: 123456
lock4j:
aop:
# Lock4j注解是否启用
enabled: false
config:
# ===================== 是否开启测试环境 =====================
TestVersion: false
# ===================== ApacheShardingSphere 配置开关 =====================
sharding-sphere-enabled: false
# ===================== 文件存储配置-Start =====================
file-storage: #文件存储配置,不使用的情况下可以不写
default-platform: local-plus-1 #默认使用的存储平台
thumbnail-suffix: ".thumb.jpg" #缩略图后缀,例如【.min.jpg】【.png】
local-plus: # 本地存储升级版
- platform: local-plus-1 # 存储平台标识
enable-storage: true #启用存储
enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
domain: "" # 访问域名例如“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
# base-path: /data/work-data/upload/jnpfsoft/yunzhupaas-resources/ # 基础路径
base-path: E:/XiangMu/yunzhu/zero-resources/ # 基础路径
path-patterns: /** # 访问路径
storage-path: # 存储路径
aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
- platform: aliyun-oss-1 # 存储平台标识
enable-storage: false # 启用存储
access-key: ??
secret-key: ??
end-point: ??
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如https://abc.oss-cn-shanghai.aliyuncs.com/
base-path: hy/ # 基础路径
qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
- platform: qiniu-kodo-1 # 存储平台标识
enable-storage: false # 启用存储
access-key: ??
secret-key: ??
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如http://abc.hn-bkt.clouddn.com/
base-path: base/ # 基础路径
tencent-cos: # 腾讯云 COS
- platform: tencent-cos-1 # 存储平台标识
enable-storage: false # 启用存储
secret-id: ??
secret-key: ??
region: ?? #存仓库所在地域
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如https://abc.cos.ap-nanjing.myqcloud.com/
base-path: hy/ # 基础路径
minio: # MinIO由于 MinIO SDK 支持 AWS S3其它兼容 AWS S3 协议的存储平台也都可配置在这里
- platform: minio-1 # 存储平台标识
enable-storage: true # 启用存储
access-key: 9Y3sjaDWgbxKjXjm
secret-key: Bs2GyJwmOLpqNsQwbDjdinyUJQHtM0rc
end-point: http://192.168.0.207:9000/
bucket-name: v350
domain: ${config.file-storage.minio[0].end-point} # 访问域名,注意“/”结尾例如http://minio.abc.com/abc/
base-path: # 基础路径
# ===================== 文件存储配置-End =====================
# ===================== 第三方登录配置-Start =====================
socials:
# 第三方登录功能开关(false-关闭true-开启)
socials-enabled: false
config:
- # 微信
provider: wechat_open
client-id: your-client-id
client-secret: your-client-secret
- # qq
provider: qq
client-id: your-client-id
client-secret: your-client-secret
- # 企业微信
provider: wechat_enterprise
client-id: your-client-id
client-secret: your-client-secret
agentId: your-agentId
- # 钉钉
provider: dingtalk
client-id: your-client-id
client-secret: your-client-secret
agentId: your-agentId
- # 飞书
provider: feishu
client-id: your-client-id
client-secret: your-client-secret
- # 小程序
provider: wechat_applets
client-id: your-client-id
client-secret: your-client-secret
# ===================== 第三方登录配置-End =====================
# ===================== 任务调度配置-Start =====================
xxl:
job:
accessToken: '432e62f3b488bc861d91b0e274e850cc'
i18n: zh_CN
logretentiondays: 30
triggerpool:
fast:
max: 200
slow:
max: 100
# xxl-job服务端地址
admin:
addresses: http://127.0.0.1:30020/xxl-job-admin/
executor:
address: ''
appname: xxl-job-executor-sample1
ip: ''
logpath: /data/applogs/xxl-job/jobhandler
logretentiondays: 30
port: 39999
# rest调用xxl-job接口地址
admin:
register:
handle-query-address: ${xxl.job.admin.addresses}api/handler/queryList
job-info-address: ${xxl.job.admin.addresses}api/jobinfo
log-query-address: ${xxl.job.admin.addresses}api/log
task-list-address: ${xxl.job.admin.addresses}api/ScheduleTask/List
task-info-address: ${xxl.job.admin.addresses}api/ScheduleTask/getInfo
task-save-address: ${xxl.job.admin.addresses}api/ScheduleTask
task-update-address: ${xxl.job.admin.addresses}api/ScheduleTask
task-remove-address: ${xxl.job.admin.addresses}api/ScheduleTask/remove
task-start-or-remove-address: ${xxl.job.admin.addresses}api/ScheduleTask/updateTask
# ===================== 任务调度配置-End =====================
# ===================== 单点登录(SSO)配置-Start =====================
yunzhupaas:
sso:
# ===================== 单点登录(用户信息拉取)配置-Start =====================
connector:
# 是否开启用户信息拉取
enabled: false
# ===================== 单点登录(用户信息拉取)配置-End =====================
# ===================== 单点登录(用户信息推送)配置-Start =====================
pull:
# 是否开启用户信息推送
enabled: false
create-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account
replace-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account
change-password-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account/changePassword
delete-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account
credential-type: Basic
user-name: 747887288041603072
password: MYgMMjIwNzIwMjIxNTU4MTAxNzQlKQ
# ===================== 单点登录(用户信息推送)配置-End =====================
oauth:
#启用单点登录, 普通登录不可用
ssoEnabled: false
#轮询票据有效期
ticketTimeout: 120
#默认单点登录协议
defaultSSO: cas
#后端登录接口地址
loginPath: http://127.0.0.1:30000/api/oauth/Login
#login:
#JWT生成秘钥 不填写为默认值
#jwtSecretKey: WviMjFNC72VKwGqm5LPoheQo5XN9iN4d
sso:
#单点登录系统地址
baseUrl: http://127.0.0.1:8527
#登录成功后跳转到前端的页面
sucessFrontUrl: http://127.0.0.1:3100/sso
#错误信息是否输出到页面
ticketOutMessage: false
#logoutFrontUrl: http://sso.maxkey.top:8527/maxkey
#单点注销后端接口地址, 配置启用后YUNZHUPAAS退出会请求单点系统退出, 触发单点注销退出全部应用
#ssoLogoutApiUrl: ${oauth.sso.baseUrl}/sign/logout
auth2:
enabled: true
clientId: 747887288041603072
clientSecret: MYgMMjIwNzIwMjIxNTU4MTAxNzQlKQ
baseUrl: ${oauth.sso.baseUrl}
authorizeUrl: ${oauth.sso.auth2.baseUrl}/sign/authz/oauth/v20/authorize
accessTokenUrl: ${oauth.sso.auth2.baseUrl}/sign/authz/oauth/v20/token
userInfoUrl: ${oauth.sso.auth2.baseUrl}/sign/api/oauth/v20/me
cas:
enabled: true
baseUrl: ${oauth.sso.baseUrl}
serverLoginUrl: ${oauth.sso.cas.baseUrl}/sign/authz/cas/login
serverValidateUrl: ${oauth.sso.cas.baseUrl}/sign/authz/cas
# ===================== 单点登录(SSO)配置-End =====================
userUrl: http://192.168.3.31:8000/api-web/sys/user/save

View File

@@ -0,0 +1,336 @@
# 应用服务器
server:
tomcat:
uri-encoding: UTF-8 #tomcat编码
port: 30000 #tomcat端口
spring:
messages:
basename: i18n/message
# 一天刷新一次
cache-duration: 24H
devtools: #spring开发者工具模块
restart:
enabled: true #热部署开关
freemarker:
cache: false #spring内置freemarker缓存
thymeleaf:
cache: false #spring内置thymeleaf缓存
# ===================== 数据源配置 =====================
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure #排除自动配置手动配置druid
datasource:
db-type: MySQL #数据库类型(可选值 MySQL、SQLServer、Oracle、DM、KingbaseES、PostgreSQL请严格按可选值填写)
host: 127.0.0.1
port: 3306
username: root
password: 123456
db-name: yunzhupaas_init
db-schema: #金仓达梦选填
prepare-url: #自定义url
# ===================== 动态多数据源 =====================
dynamic:
primary: master #设置默认的数据源或者数据源组,默认值即为master
strict: true #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
druid:
# 空闲时执行连接测试
test-while-idle: true
# 连接测试最小间隔
time-between-eviction-runs-millis: 60000
# 获取连接等待3秒 根据网络情况设定
max-wait: 3000
# 初始化4个连接
initial-size: 4
# 最大20个连接
max-active: 20
# 最少保持4个空闲连接
min-idle: 4
# 空闲连接保活, 超过配置的空闲时间会进行连接检查完成保活操作(数据库自身会断开达到空闲时间的连接, 程序使用断开的连接会报错)
keep-alive: true
# 连接超时
connect-timeout: 10000
# 连接超时
socket-timeout: 10000
# 查询超时
query-timeout: 90000
# 事务查询超时
transaction-query-timeout: 90000
# 解除注释后Druid连接池打印SQL语句 忽略日志等级配置
# filters: slf4j
slf4j:
statementLogEnabled: true
resultSetLogEnabled: false
connectionLogEnabled: false
dataSourceLogEnabled: false
statementCreateAfterLogEnabled: false
statementCloseAfterLogEnabled: false
statementExecuteAfterLogEnabled: false
#打印SQL替换参数
statementExecutableSqlLogEnable: true
statementPrepareAfterLogEnabled: false
statementPrepareCallAfterLogEnabled: false
statementParameterSetLogEnabled: false
# datasource:
# master:
# url: jdbc:mysql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.dbname}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
# username: ${spring.datasource.username}
# password: ${spring.datasource.password}
# driver-class-name: com.mysql.cj.jdbc.Driver
# ===================== Redis配置-Start =====================
# redis单机模式
redis:
database: 1 #缓存库编号
host: 127.0.0.1
port: 6379
password: 123456 # 密码为空时,请将本行注释
timeout: 3000 #超时时间(单位:秒)
lettuce: #Lettuce为Redis的Java驱动包
pool:
max-active: 8 # 连接池最大连接数
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
min-idle: 0 # 连接池中的最小空闲连接
max-idle: 8 # 连接池中的最大空闲连接
# redis集群模式
# redis:
# cluster:
# nodes:
# - 192.168.0.225:6380
# - 192.168.0.225:6381
# - 192.168.0.225:6382
# - 192.168.0.225:6383
# - 192.168.0.225:6384
# - 192.168.0.225:6385
# password: 123456 # 密码为空时,请将本行注释
# timeout: 3000 # 超时时间(单位:秒)
# lettuce: #Lettuce为Redis的Java驱动包
# pool:
# max-active: 8 # 连接池最大连接数
# max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
# min-idle: 0 # 连接池中的最小空闲连接
# max-idle: 8 # 连接池中的最大空闲连接
# ===================== Redis配置-End =====================
# ===================== 单点登录(用户信息同步)配置-Start =====================
cloud:
stream:
# 若使用RocketMQ-Start
rocketmq:
binder:
name-server: 192.168.10.6:30094
group: maxkey_identity
# 若使用RocketMQ-End
# 若使用RabbitMQ-Start
# binders:
# defaultRabbit: # 表示定义的名称用于binding整合
# type: rabbit # 消息组件类型
# environment: # 设置rabbitmq的相关环境配置
# spring:
# rabbitmq:
# host: 192.168.10.6
# port: 5672
# username: rabbitmq
# password: rabbitmq
# 若使用RabbitMQ-End
# 若使用Kafka-Start
# kafka:
# # KafkaBinderConfigurationProperties
# binder:
# brokers: 192.168.10.6:9092
# 若使用Kafka-End
bindings:
ssoEventReceiver-in-0:
content-type: text/json
destination: MXK_IDENTITY_MAIN_TOPIC
group: maxkey_identity
# ===================== 单点登录(用户信息同步)配置-End =====================
# SpringDoc接口文档 访问地址http://127.0.0.1:30000/doc.html
springdoc:
default-flat-param-object: true
api-docs:
enabled: true
#SpringDoc增强
#knife4j:
# enable: true
# basic: #接口文档访问鉴权
# enable: true
# username: yunzhupaas
# password: 123456
lock4j:
aop:
# Lock4j注解是否启用
enabled: false
config:
# ===================== 是否开启测试环境 =====================
TestVersion: false
# ===================== ApacheShardingSphere 配置开关 =====================
sharding-sphere-enabled: false
# ===================== 文件存储配置-Start =====================
file-storage: #文件存储配置,不使用的情况下可以不写
default-platform: local-plus-1 #默认使用的存储平台
thumbnail-suffix: ".thumb.jpg" #缩略图后缀,例如【.min.jpg】【.png】
local-plus: # 本地存储升级版
- platform: local-plus-1 # 存储平台标识
enable-storage: true #启用存储
enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
domain: "" # 访问域名例如“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
base-path: D:/project/yunzhupaas-resources/ # 基础路径
path-patterns: /** # 访问路径
storage-path: # 存储路径
aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
- platform: aliyun-oss-1 # 存储平台标识
enable-storage: false # 启用存储
access-key: ??
secret-key: ??
end-point: ??
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如https://abc.oss-cn-shanghai.aliyuncs.com/
base-path: hy/ # 基础路径
qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
- platform: qiniu-kodo-1 # 存储平台标识
enable-storage: false # 启用存储
access-key: ??
secret-key: ??
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如http://abc.hn-bkt.clouddn.com/
base-path: base/ # 基础路径
tencent-cos: # 腾讯云 COS
- platform: tencent-cos-1 # 存储平台标识
enable-storage: false # 启用存储
secret-id: ??
secret-key: ??
region: ?? #存仓库所在地域
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如https://abc.cos.ap-nanjing.myqcloud.com/
base-path: hy/ # 基础路径
minio: # MinIO由于 MinIO SDK 支持 AWS S3其它兼容 AWS S3 协议的存储平台也都可配置在这里
- platform: minio-1 # 存储平台标识
enable-storage: true # 启用存储
access-key: 9Y3sjaDWgbxKjXjm
secret-key: Bs2GyJwmOLpqNsQwbDjdinyUJQHtM0rc
end-point: http://192.168.0.207:9000/
bucket-name: v350
domain: ${config.file-storage.minio[0].end-point} # 访问域名,注意“/”结尾例如http://minio.abc.com/abc/
base-path: # 基础路径
# ===================== 文件存储配置-End =====================
# ===================== 第三方登录配置-Start =====================
socials:
# 第三方登录功能开关(false-关闭true-开启)
socials-enabled: false
config:
- # 微信
provider: wechat_open
client-id: your-client-id
client-secret: your-client-secret
- # qq
provider: qq
client-id: your-client-id
client-secret: your-client-secret
- # 企业微信
provider: wechat_enterprise
client-id: your-client-id
client-secret: your-client-secret
agentId: your-agentId
- # 钉钉
provider: dingtalk
client-id: your-client-id
client-secret: your-client-secret
agentId: your-agentId
- # 飞书
provider: feishu
client-id: your-client-id
client-secret: your-client-secret
- # 小程序
provider: wechat_applets
client-id: your-client-id
client-secret: your-client-secret
# ===================== 第三方登录配置-End =====================
# ===================== 任务调度配置-Start =====================
xxl:
job:
accessToken: '432e62f3b488bc861d91b0e274e850cc'
i18n: zh_CN
logretentiondays: 30
triggerpool:
fast:
max: 200
slow:
max: 100
# xxl-job服务端地址
admin:
addresses: http://127.0.0.1:30020/xxl-job-admin/
executor:
address: ''
appname: xxl-job-executor-sample1
ip: ''
logpath: /data/applogs/xxl-job/jobhandler
logretentiondays: 30
port: 39999
# rest调用xxl-job接口地址
admin:
register:
handle-query-address: ${xxl.job.admin.addresses}api/handler/queryList
job-info-address: ${xxl.job.admin.addresses}api/jobinfo
log-query-address: ${xxl.job.admin.addresses}api/log
task-list-address: ${xxl.job.admin.addresses}api/ScheduleTask/List
task-info-address: ${xxl.job.admin.addresses}api/ScheduleTask/getInfo
task-save-address: ${xxl.job.admin.addresses}api/ScheduleTask
task-update-address: ${xxl.job.admin.addresses}api/ScheduleTask
task-remove-address: ${xxl.job.admin.addresses}api/ScheduleTask/remove
task-start-or-remove-address: ${xxl.job.admin.addresses}api/ScheduleTask/updateTask
# ===================== 任务调度配置-End =====================
# ===================== 单点登录(SSO)配置-Start =====================
yunzhupaas:
sso:
# ===================== 单点登录(用户信息拉取)配置-Start =====================
connector:
# 是否开启用户信息拉取
enabled: false
# ===================== 单点登录(用户信息拉取)配置-End =====================
# ===================== 单点登录(用户信息推送)配置-Start =====================
pull:
# 是否开启用户信息推送
enabled: false
create-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account
replace-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account
change-password-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account/changePassword
delete-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account
credential-type: Basic
user-name: 747887288041603072
password: MYgMMjIwNzIwMjIxNTU4MTAxNzQlKQ
# ===================== 单点登录(用户信息推送)配置-End =====================
oauth:
#启用单点登录, 普通登录不可用
ssoEnabled: false
#轮询票据有效期
ticketTimeout: 120
#默认单点登录协议
defaultSSO: cas
#后端登录接口地址
loginPath: http://127.0.0.1:30000/api/oauth/Login
#轮询登录模式是否输出结果
ticketOutMessage: false
login:
#JWT生成秘钥 不填写为默认值
#jwtSecretKey: WviMjFNC72VKwGqm5LPoheQo5XN9iN4d
sso:
#登录成功后跳转到前端的页面
sucessFrontUrl: http://127.0.0.1:3000/sso
#logoutFrontUrl: http://sso.maxkey.top:8527/maxkey
auth2:
enabled: true
clientId: 747887288041603072
clientSecret: MYgMMjIwNzIwMjIxNTU4MTAxNzQlKQ
baseUrl: http://127.0.0.1:8527
authorizeUrl: ${oauth.sso.auth2.baseUrl}/sign/authz/oauth/v20/authorize
accessTokenUrl: ${oauth.sso.auth2.baseUrl}/sign/authz/oauth/v20/token
userInfoUrl: ${oauth.sso.auth2.baseUrl}/sign/api/oauth/v20/me
cas:
enabled: true
baseUrl: ${oauth.sso.auth2.baseUrl}
serverLoginUrl: ${oauth.sso.cas.baseUrl}/sign/authz/cas/login
serverValidateUrl: ${oauth.sso.cas.baseUrl}/sign/authz/cas
# ===================== 单点登录(SSO)配置-End =====================

View File

@@ -0,0 +1,370 @@
# 应用服务器
server:
tomcat:
uri-encoding: UTF-8 #tomcat编码
port: 40001 #tomcat端口
spring:
messages:
basename: i18n/message
# 一天刷新一次
cache-duration: 24H
devtools: #spring开发者工具模块
restart:
enabled: true #热部署开关
freemarker:
cache: false #spring内置freemarker缓存
thymeleaf:
cache: false #spring内置thymeleaf缓存
# ===================== 数据源配置 =====================
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure #排除自动配置手动配置druid
datasource:
db-type: MySQL #数据库类型(可选值 MySQL、SQLServer、Oracle、DM8、KingbaseES、PostgreSQL请严格按可选值填写)
# host: aliyun.szlecheng.cn
host: mysql.szlecheng.cn
port: 13306
username: yunzhupass
password: '@yunzhupass'
db-name: pord_yunzhupass
db-schema: #金仓达梦选填
prepare-url: #自定义url
# ===================== 动态多数据源 =====================
dynamic:
primary: master #设置默认的数据源或者数据源组,默认值即为master
strict: true #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
druid:
# 空闲时执行连接测试
test-while-idle: true
# 连接测试最小间隔
time-between-eviction-runs-millis: 60000
# 获取连接等待3秒 根据网络情况设定
max-wait: 3000
# 初始化4个连接
initial-size: 4
# 最大20个连接
max-active: 20
# 最少保持4个空闲连接
min-idle: 4
# 空闲连接保活, 超过配置的空闲时间会进行连接检查完成保活操作(数据库自身会断开达到空闲时间的连接, 程序使用断开的连接会报错)
keep-alive: true
# 连接超时
connect-timeout: 10000
# 连接超时
socket-timeout: 10000
# 查询超时
query-timeout: 90000
# 事务查询超时
transaction-query-timeout: 90000
# 解除注释后Druid连接池打印SQL语句 忽略日志等级配置
# filters: slf4j
slf4j:
statementLogEnabled: true
resultSetLogEnabled: false
connectionLogEnabled: false
dataSourceLogEnabled: false
statementCreateAfterLogEnabled: false
statementCloseAfterLogEnabled: false
statementExecuteAfterLogEnabled: false
#打印SQL替换参数
statementExecutableSqlLogEnable: true
statementPrepareAfterLogEnabled: false
statementPrepareCallAfterLogEnabled: false
statementParameterSetLogEnabled: false
# datasource:
# master:
# url: jdbc:mysql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.dbname}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
# username: ${spring.datasource.username}
# password: ${spring.datasource.password}
# driver-class-name: com.mysql.cj.jdbc.Driver
# ===================== Redis配置 =====================
# redis单机模式
data:
redis:
database: 10
host: 127.0.0.1
port: 6379
# password: redis_JtjYRD # 密码为空时,请将本行注释
timeout: 3000 #超时时间(单位:秒)
lettuce: #Lettuce为Redis的Java驱动包
pool:
max-active: 8 # 连接池最大连接数
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
min-idle: 0 # 连接池中的最小空闲连接
max-idle: 8 # 连接池中的最大空闲连接
# redis集群模式
# redis:
# cluster:
# nodes:
# - 192.168.0.225:6380
# - 192.168.0.225:6381
# - 192.168.0.225:6382
# - 192.168.0.225:6383
# - 192.168.0.225:6384
# - 192.168.0.225:6385
# password: 123456 # 密码为空时,请将本行注释
# timeout: 3000 # 超时时间(单位:秒)
# lettuce: #Lettuce为Redis的Java驱动包
# pool:
# max-active: 8 # 连接池最大连接数
# max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
# min-idle: 0 # 连接池中的最小空闲连接
# max-idle: 8 # 连接池中的最大空闲连接
# ===================== Redis配置-End =====================
# ===================== 单点登录(用户信息同步)配置-Start =====================
cloud:
stream:
# 若使用RocketMQ-Start
rocketmq:
binder:
name-server: 192.168.10.6:30094
group: maxkey_identity
# 若使用RocketMQ-End
# 若使用RabbitMQ-Start
# binders:
# defaultRabbit: # 表示定义的名称用于binding整合
# type: rabbit # 消息组件类型
# environment: # 设置rabbitmq的相关环境配置
# spring:
# rabbitmq:
# host: 192.168.10.6
# port: 5672
# username: rabbitmq
# password: rabbitmq
# 若使用RabbitMQ-End
# 若使用Kafka-Start
# kafka:
# # KafkaBinderConfigurationProperties
# binder:
# brokers: 192.168.10.6:9092
# 若使用Kafka-End
bindings:
ssoEventReceiver-in-0:
content-type: text/json
destination: MXK_IDENTITY_MAIN_TOPIC
group: maxkey_identity
# ===================== 单点登录(用户信息同步)配置-End =====================
# ===================== AI配置-Start =====================
ai:
openai:
enabled: true
# 超时时间, 秒, 根据AI平台性能调整超时时间
timeout: 300
# 阿里百联平台
api-host: https://dashscope.aliyuncs.com/compatible-mode/
api-key: sk-def0e6d9d0f8497cb5bcfff8c0c19935
chat:
mode: qwen-max
# GPT转发平台
# api-host: https://api.chatanywhere.tech/
# api-key:
# chat:
# mode: gpt-3.5-turbo
# DeepSeek
# api-host: https://api.deepseek.com/v1/
# api-key:
# chat:
# mode: deepseek-chat
# ===================== AI配置-End =====================
# SpringDoc接口文档 访问地址http://127.0.0.1:30000/doc.html
springdoc:
default-flat-param-object: true
api-docs:
enabled: true
#SpringDoc增强
#knife4j:
# enable: true
# basic: #接口文档访问鉴权
# enable: true
# username: yunzhupaas
# password: 123456
lock4j:
aop:
# Lock4j注解是否启用
enabled: false
config:
# ===================== 是否开启测试环境 =====================
TestVersion: false
# ===================== ApacheShardingSphere 配置开关 =====================
sharding-sphere-enabled: false
# ===================== 文件存储配置-Start =====================
file-storage: #文件存储配置,不使用的情况下可以不写
default-platform: local-plus-1 #默认使用的存储平台
thumbnail-suffix: ".thumb.jpg" #缩略图后缀,例如【.min.jpg】【.png】
local-plus: # 本地存储升级版
- platform: local-plus-1 # 存储平台标识
enable-storage: true #启用存储
enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
domain: "" # 访问域名例如“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
# base-path: /data/work-data/upload/jnpfsoft/yunzhupaas-resources/ # 基础路径
base-path: E:/XiangMu/yunzhu/zero-resources/ # 基础路径
path-patterns: /** # 访问路径
storage-path: # 存储路径
aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
- platform: aliyun-oss-1 # 存储平台标识
enable-storage: false # 启用存储
access-key: ??
secret-key: ??
end-point: ??
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如https://abc.oss-cn-shanghai.aliyuncs.com/
base-path: hy/ # 基础路径
qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
- platform: qiniu-kodo-1 # 存储平台标识
enable-storage: false # 启用存储
access-key: ??
secret-key: ??
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如http://abc.hn-bkt.clouddn.com/
base-path: base/ # 基础路径
tencent-cos: # 腾讯云 COS
- platform: tencent-cos-1 # 存储平台标识
enable-storage: false # 启用存储
secret-id: ??
secret-key: ??
region: ?? #存仓库所在地域
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如https://abc.cos.ap-nanjing.myqcloud.com/
base-path: hy/ # 基础路径
minio: # MinIO由于 MinIO SDK 支持 AWS S3其它兼容 AWS S3 协议的存储平台也都可配置在这里
- platform: minio-1 # 存储平台标识
enable-storage: true # 启用存储
access-key: 9Y3sjaDWgbxKjXjm
secret-key: Bs2GyJwmOLpqNsQwbDjdinyUJQHtM0rc
end-point: http://192.168.0.207:9000/
bucket-name: v350
domain: ${config.file-storage.minio[0].end-point} # 访问域名,注意“/”结尾例如http://minio.abc.com/abc/
base-path: # 基础路径
# ===================== 文件存储配置-End =====================
# ===================== 第三方登录配置-Start =====================
socials:
# 第三方登录功能开关(false-关闭true-开启)
socials-enabled: false
config:
- # 微信
provider: wechat_open
client-id: your-client-id
client-secret: your-client-secret
- # qq
provider: qq
client-id: your-client-id
client-secret: your-client-secret
- # 企业微信
provider: wechat_enterprise
client-id: your-client-id
client-secret: your-client-secret
agentId: your-agentId
- # 钉钉
provider: dingtalk
client-id: your-client-id
client-secret: your-client-secret
agentId: your-agentId
- # 飞书
provider: feishu
client-id: your-client-id
client-secret: your-client-secret
- # 小程序
provider: wechat_applets
client-id: your-client-id
client-secret: your-client-secret
# ===================== 第三方登录配置-End =====================
# ===================== 任务调度配置-Start =====================
xxl:
job:
accessToken: '432e62f3b488bc861d91b0e274e850cc'
i18n: zh_CN
logretentiondays: 30
triggerpool:
fast:
max: 200
slow:
max: 100
# xxl-job服务端地址
admin:
addresses: http://127.0.0.1:30020/xxl-job-admin/
executor:
address: ''
appname: xxl-job-executor-sample1
ip: ''
logpath: /data/applogs/xxl-job/jobhandler
logretentiondays: 30
port: 39999
# rest调用xxl-job接口地址
admin:
register:
handle-query-address: ${xxl.job.admin.addresses}api/handler/queryList
job-info-address: ${xxl.job.admin.addresses}api/jobinfo
log-query-address: ${xxl.job.admin.addresses}api/log
task-list-address: ${xxl.job.admin.addresses}api/ScheduleTask/List
task-info-address: ${xxl.job.admin.addresses}api/ScheduleTask/getInfo
task-save-address: ${xxl.job.admin.addresses}api/ScheduleTask
task-update-address: ${xxl.job.admin.addresses}api/ScheduleTask
task-remove-address: ${xxl.job.admin.addresses}api/ScheduleTask/remove
task-start-or-remove-address: ${xxl.job.admin.addresses}api/ScheduleTask/updateTask
# ===================== 任务调度配置-End =====================
# ===================== 单点登录(SSO)配置-Start =====================
yunzhupaas:
sso:
# ===================== 单点登录(用户信息拉取)配置-Start =====================
connector:
# 是否开启用户信息拉取
enabled: false
# ===================== 单点登录(用户信息拉取)配置-End =====================
# ===================== 单点登录(用户信息推送)配置-Start =====================
pull:
# 是否开启用户信息推送
enabled: false
create-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account
replace-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account
change-password-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account/changePassword
delete-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account
credential-type: Basic
user-name: 747887288041603072
password: MYgMMjIwNzIwMjIxNTU4MTAxNzQlKQ
# ===================== 单点登录(用户信息推送)配置-End =====================
oauth:
#启用单点登录, 普通登录不可用
ssoEnabled: false
#轮询票据有效期
ticketTimeout: 120
#默认单点登录协议
defaultSSO: cas
#后端登录接口地址
loginPath: http://127.0.0.1:30000/api/oauth/Login
#login:
#JWT生成秘钥 不填写为默认值
#jwtSecretKey: WviMjFNC72VKwGqm5LPoheQo5XN9iN4d
sso:
#单点登录系统地址
baseUrl: http://127.0.0.1:8527
#登录成功后跳转到前端的页面
sucessFrontUrl: http://127.0.0.1:3100/sso
#错误信息是否输出到页面
ticketOutMessage: false
#logoutFrontUrl: http://sso.maxkey.top:8527/maxkey
#单点注销后端接口地址, 配置启用后YUNZHUPAAS退出会请求单点系统退出, 触发单点注销退出全部应用
#ssoLogoutApiUrl: ${oauth.sso.baseUrl}/sign/logout
auth2:
enabled: true
clientId: 747887288041603072
clientSecret: MYgMMjIwNzIwMjIxNTU4MTAxNzQlKQ
baseUrl: ${oauth.sso.baseUrl}
authorizeUrl: ${oauth.sso.auth2.baseUrl}/sign/authz/oauth/v20/authorize
accessTokenUrl: ${oauth.sso.auth2.baseUrl}/sign/authz/oauth/v20/token
userInfoUrl: ${oauth.sso.auth2.baseUrl}/sign/api/oauth/v20/me
cas:
enabled: true
baseUrl: ${oauth.sso.baseUrl}
serverLoginUrl: ${oauth.sso.cas.baseUrl}/sign/authz/cas/login
serverValidateUrl: ${oauth.sso.cas.baseUrl}/sign/authz/cas
# ===================== 单点登录(SSO)配置-End =====================
userUrl: http://192.168.3.31:8000/api-web/sys/user/save

View File

@@ -0,0 +1,370 @@
# 应用服务器
server:
tomcat:
uri-encoding: UTF-8 #tomcat编码
port: 40001 #tomcat端口
spring:
messages:
basename: i18n/message
# 一天刷新一次
cache-duration: 24H
devtools: #spring开发者工具模块
restart:
enabled: true #热部署开关
freemarker:
cache: false #spring内置freemarker缓存
thymeleaf:
cache: false #spring内置thymeleaf缓存
# ===================== 数据源配置 =====================
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure #排除自动配置手动配置druid
datasource:
db-type: MySQL #数据库类型(可选值 MySQL、SQLServer、Oracle、DM8、KingbaseES、PostgreSQL请严格按可选值填写)
# host: aliyun.szlecheng.cn
host: mysql.szlecheng.cn
port: 13306
username: oa_yunzhupaas
password: OAYUNZHUPAAS
db-name: oa_yunzhupass
db-schema: #金仓达梦选填
prepare-url: #自定义url
# ===================== 动态多数据源 =====================
dynamic:
primary: master #设置默认的数据源或者数据源组,默认值即为master
strict: true #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
druid:
# 空闲时执行连接测试
test-while-idle: true
# 连接测试最小间隔
time-between-eviction-runs-millis: 60000
# 获取连接等待3秒 根据网络情况设定
max-wait: 3000
# 初始化4个连接
initial-size: 4
# 最大20个连接
max-active: 20
# 最少保持4个空闲连接
min-idle: 4
# 空闲连接保活, 超过配置的空闲时间会进行连接检查完成保活操作(数据库自身会断开达到空闲时间的连接, 程序使用断开的连接会报错)
keep-alive: true
# 连接超时
connect-timeout: 10000
# 连接超时
socket-timeout: 10000
# 查询超时
query-timeout: 90000
# 事务查询超时
transaction-query-timeout: 90000
# 解除注释后Druid连接池打印SQL语句 忽略日志等级配置
# filters: slf4j
slf4j:
statementLogEnabled: true
resultSetLogEnabled: false
connectionLogEnabled: false
dataSourceLogEnabled: false
statementCreateAfterLogEnabled: false
statementCloseAfterLogEnabled: false
statementExecuteAfterLogEnabled: false
#打印SQL替换参数
statementExecutableSqlLogEnable: true
statementPrepareAfterLogEnabled: false
statementPrepareCallAfterLogEnabled: false
statementParameterSetLogEnabled: false
# datasource:
# master:
# url: jdbc:mysql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.dbname}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
# username: ${spring.datasource.username}
# password: ${spring.datasource.password}
# driver-class-name: com.mysql.cj.jdbc.Driver
# ===================== Redis配置 =====================
# redis单机模式
data:
redis:
database: 10
host: 127.0.0.1
port: 6379
# password: redis_JtjYRD # 密码为空时,请将本行注释
timeout: 3000 #超时时间(单位:秒)
lettuce: #Lettuce为Redis的Java驱动包
pool:
max-active: 8 # 连接池最大连接数
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
min-idle: 0 # 连接池中的最小空闲连接
max-idle: 8 # 连接池中的最大空闲连接
# redis集群模式
# redis:
# cluster:
# nodes:
# - 192.168.0.225:6380
# - 192.168.0.225:6381
# - 192.168.0.225:6382
# - 192.168.0.225:6383
# - 192.168.0.225:6384
# - 192.168.0.225:6385
# password: 123456 # 密码为空时,请将本行注释
# timeout: 3000 # 超时时间(单位:秒)
# lettuce: #Lettuce为Redis的Java驱动包
# pool:
# max-active: 8 # 连接池最大连接数
# max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
# min-idle: 0 # 连接池中的最小空闲连接
# max-idle: 8 # 连接池中的最大空闲连接
# ===================== Redis配置-End =====================
# ===================== 单点登录(用户信息同步)配置-Start =====================
cloud:
stream:
# 若使用RocketMQ-Start
rocketmq:
binder:
name-server: 192.168.10.6:30094
group: maxkey_identity
# 若使用RocketMQ-End
# 若使用RabbitMQ-Start
# binders:
# defaultRabbit: # 表示定义的名称用于binding整合
# type: rabbit # 消息组件类型
# environment: # 设置rabbitmq的相关环境配置
# spring:
# rabbitmq:
# host: 192.168.10.6
# port: 5672
# username: rabbitmq
# password: rabbitmq
# 若使用RabbitMQ-End
# 若使用Kafka-Start
# kafka:
# # KafkaBinderConfigurationProperties
# binder:
# brokers: 192.168.10.6:9092
# 若使用Kafka-End
bindings:
ssoEventReceiver-in-0:
content-type: text/json
destination: MXK_IDENTITY_MAIN_TOPIC
group: maxkey_identity
# ===================== 单点登录(用户信息同步)配置-End =====================
# ===================== AI配置-Start =====================
ai:
openai:
enabled: true
# 超时时间, 秒, 根据AI平台性能调整超时时间
timeout: 300
# 阿里百联平台
api-host: https://dashscope.aliyuncs.com/compatible-mode/
api-key: sk-def0e6d9d0f8497cb5bcfff8c0c19935
chat:
mode: qwen-max
# GPT转发平台
# api-host: https://api.chatanywhere.tech/
# api-key:
# chat:
# mode: gpt-3.5-turbo
# DeepSeek
# api-host: https://api.deepseek.com/v1/
# api-key:
# chat:
# mode: deepseek-chat
# ===================== AI配置-End =====================
# SpringDoc接口文档 访问地址http://127.0.0.1:30000/doc.html
springdoc:
default-flat-param-object: true
api-docs:
enabled: true
#SpringDoc增强
#knife4j:
# enable: true
# basic: #接口文档访问鉴权
# enable: true
# username: yunzhupaas
# password: 123456
lock4j:
aop:
# Lock4j注解是否启用
enabled: false
config:
# ===================== 是否开启测试环境 =====================
TestVersion: false
# ===================== ApacheShardingSphere 配置开关 =====================
sharding-sphere-enabled: false
# ===================== 文件存储配置-Start =====================
file-storage: #文件存储配置,不使用的情况下可以不写
default-platform: local-plus-1 #默认使用的存储平台
thumbnail-suffix: ".thumb.jpg" #缩略图后缀,例如【.min.jpg】【.png】
local-plus: # 本地存储升级版
- platform: local-plus-1 # 存储平台标识
enable-storage: true #启用存储
enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
domain: "" # 访问域名例如“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
# base-path: /data/work-data/upload/jnpfsoft/yunzhupaas-resources/ # 基础路径
base-path: E:/XiangMu/yunzhu/zero-resources/ # 基础路径
path-patterns: /** # 访问路径
storage-path: # 存储路径
aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
- platform: aliyun-oss-1 # 存储平台标识
enable-storage: false # 启用存储
access-key: ??
secret-key: ??
end-point: ??
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如https://abc.oss-cn-shanghai.aliyuncs.com/
base-path: hy/ # 基础路径
qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
- platform: qiniu-kodo-1 # 存储平台标识
enable-storage: false # 启用存储
access-key: ??
secret-key: ??
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如http://abc.hn-bkt.clouddn.com/
base-path: base/ # 基础路径
tencent-cos: # 腾讯云 COS
- platform: tencent-cos-1 # 存储平台标识
enable-storage: false # 启用存储
secret-id: ??
secret-key: ??
region: ?? #存仓库所在地域
bucket-name: ??
domain: ?? # 访问域名,注意“/”结尾例如https://abc.cos.ap-nanjing.myqcloud.com/
base-path: hy/ # 基础路径
minio: # MinIO由于 MinIO SDK 支持 AWS S3其它兼容 AWS S3 协议的存储平台也都可配置在这里
- platform: minio-1 # 存储平台标识
enable-storage: true # 启用存储
access-key: 9Y3sjaDWgbxKjXjm
secret-key: Bs2GyJwmOLpqNsQwbDjdinyUJQHtM0rc
end-point: http://192.168.0.207:9000/
bucket-name: v350
domain: ${config.file-storage.minio[0].end-point} # 访问域名,注意“/”结尾例如http://minio.abc.com/abc/
base-path: # 基础路径
# ===================== 文件存储配置-End =====================
# ===================== 第三方登录配置-Start =====================
socials:
# 第三方登录功能开关(false-关闭true-开启)
socials-enabled: false
config:
- # 微信
provider: wechat_open
client-id: your-client-id
client-secret: your-client-secret
- # qq
provider: qq
client-id: your-client-id
client-secret: your-client-secret
- # 企业微信
provider: wechat_enterprise
client-id: your-client-id
client-secret: your-client-secret
agentId: your-agentId
- # 钉钉
provider: dingtalk
client-id: your-client-id
client-secret: your-client-secret
agentId: your-agentId
- # 飞书
provider: feishu
client-id: your-client-id
client-secret: your-client-secret
- # 小程序
provider: wechat_applets
client-id: your-client-id
client-secret: your-client-secret
# ===================== 第三方登录配置-End =====================
# ===================== 任务调度配置-Start =====================
xxl:
job:
accessToken: '432e62f3b488bc861d91b0e274e850cc'
i18n: zh_CN
logretentiondays: 30
triggerpool:
fast:
max: 200
slow:
max: 100
# xxl-job服务端地址
admin:
addresses: http://127.0.0.1:30020/xxl-job-admin/
executor:
address: ''
appname: xxl-job-executor-sample1
ip: ''
logpath: /data/applogs/xxl-job/jobhandler
logretentiondays: 30
port: 39999
# rest调用xxl-job接口地址
admin:
register:
handle-query-address: ${xxl.job.admin.addresses}api/handler/queryList
job-info-address: ${xxl.job.admin.addresses}api/jobinfo
log-query-address: ${xxl.job.admin.addresses}api/log
task-list-address: ${xxl.job.admin.addresses}api/ScheduleTask/List
task-info-address: ${xxl.job.admin.addresses}api/ScheduleTask/getInfo
task-save-address: ${xxl.job.admin.addresses}api/ScheduleTask
task-update-address: ${xxl.job.admin.addresses}api/ScheduleTask
task-remove-address: ${xxl.job.admin.addresses}api/ScheduleTask/remove
task-start-or-remove-address: ${xxl.job.admin.addresses}api/ScheduleTask/updateTask
# ===================== 任务调度配置-End =====================
# ===================== 单点登录(SSO)配置-Start =====================
yunzhupaas:
sso:
# ===================== 单点登录(用户信息拉取)配置-Start =====================
connector:
# 是否开启用户信息拉取
enabled: false
# ===================== 单点登录(用户信息拉取)配置-End =====================
# ===================== 单点登录(用户信息推送)配置-Start =====================
pull:
# 是否开启用户信息推送
enabled: false
create-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account
replace-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account
change-password-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account/changePassword
delete-rest-address: http://localhost:9526/sso-mgt-api/api/idm/Account
credential-type: Basic
user-name: 747887288041603072
password: MYgMMjIwNzIwMjIxNTU4MTAxNzQlKQ
# ===================== 单点登录(用户信息推送)配置-End =====================
oauth:
#启用单点登录, 普通登录不可用
ssoEnabled: false
#轮询票据有效期
ticketTimeout: 120
#默认单点登录协议
defaultSSO: cas
#后端登录接口地址
loginPath: http://127.0.0.1:30000/api/oauth/Login
#login:
#JWT生成秘钥 不填写为默认值
#jwtSecretKey: WviMjFNC72VKwGqm5LPoheQo5XN9iN4d
sso:
#单点登录系统地址
baseUrl: http://127.0.0.1:8527
#登录成功后跳转到前端的页面
sucessFrontUrl: http://127.0.0.1:3100/sso
#错误信息是否输出到页面
ticketOutMessage: false
#logoutFrontUrl: http://sso.maxkey.top:8527/maxkey
#单点注销后端接口地址, 配置启用后YUNZHUPAAS退出会请求单点系统退出, 触发单点注销退出全部应用
#ssoLogoutApiUrl: ${oauth.sso.baseUrl}/sign/logout
auth2:
enabled: true
clientId: 747887288041603072
clientSecret: MYgMMjIwNzIwMjIxNTU4MTAxNzQlKQ
baseUrl: ${oauth.sso.baseUrl}
authorizeUrl: ${oauth.sso.auth2.baseUrl}/sign/authz/oauth/v20/authorize
accessTokenUrl: ${oauth.sso.auth2.baseUrl}/sign/authz/oauth/v20/token
userInfoUrl: ${oauth.sso.auth2.baseUrl}/sign/api/oauth/v20/me
cas:
enabled: true
baseUrl: ${oauth.sso.baseUrl}
serverLoginUrl: ${oauth.sso.cas.baseUrl}/sign/authz/cas/login
serverValidateUrl: ${oauth.sso.cas.baseUrl}/sign/authz/cas
# ===================== 单点登录(SSO)配置-End =====================
userUrl: http://192.168.3.31:8000/api-web/sys/user/save

View File

@@ -0,0 +1,163 @@
spring:
application:
name: yunzhupaas-boot
profiles:
# 指定环境配置 dev(开发环境-默认)、test(测试环境)、preview(预生产)、prod(生产环境)
active: test
servlet:
multipart: #文件传输配置
max-file-size: 100MB #单个数据大小限制
max-request-size: 100MB #请求总数据大小限制
enabled: true #是否启用分段上传支持
mvc:
#csrf-origins: ${config.FrontDomain}
cors:
# 允许跨域的域名
#allowed-origins: ${config.FrontDomain}
# 允许跨域的域名正则匹配 如需全部匹配设置为 '**', 因为包含凭据的请求不允许直接写* 这个写法可以直接返回当前请求域名
allowed-origin-patterns: '**'
# 允许跨域的请求方法 GET, POST, PUT, DELETE
allowed-methods: "*"
# 允许跨域的头部信息 Content-Type, Authorization
allowed-headers: "*"
options-max-age: 18000
headers:
server-name: ''
x-frame-options: sameorigin
x-content-type-options: disabled
x-xss-protection: enabled_mode_block
hiddenmethod: #隐式方法过滤器
filter:
enabled: true #默认开启。开启以支持PUT,DELETE表单提交方法
jackson: #序列化和反序列化json框架
serialization:
write-dates-as-timestamps: true #是否写入日期时间时间戳格式
time-zone: GMT+8 #指定日期格式化时区
main:
allow-bean-definition-overriding: true #允许同名bean后者覆盖,默认true
allow-circular-references: true #允许Bean相互引用,默认false
config:
# ===============静态资源目录映射==================
WebAnnexFilePath: WebAnnexFile
DataBackupFilePath: DataBackupFile
TemporaryFilePath: TemporaryFile
SystemFilePath: SystemFile
TemplateFilePath: TemplateFile
EmailFilePath: EmailFile
DocumentFilePath: DocumentFile
DocumentPreviewPath: DocumentPreview
UserAvatarFilePath: UserAvatar
IMContentFilePath: IMContentFile
MPMaterialFilePath: MPMaterial
TemplateCodePath: TemplateCode
BiVisualPath: BiVisualPath
# ===============功能格式限制==================
MPUploadFileType: bmp,png,jpeg,jpg,gif,mp3,wma,wav,amr,mp4
WeChatUploadFileType: jpg,png,doc,docx,ppt,pptx,xls,xlsx,pdf,txt,rar,zip,csv,amr,mp4
AllowUploadImageType: jpg,gif,png,bmp,jpeg,tiff,psd,swf,svg,pcx,dxf,wmf,emf,lic,eps,tga #允许上传图片类型
AllowUploadFileType: jpg,gif,png,bmp,jpeg,doc,docx,ppt,pptx,xls,xlsx,pdf,txt,rar,zip,csv,mp3,aac #允许上传文件类型
AllowPreviewFileType: doc,docx,xls,xlsx,ppt,pptx,pdf,jpg,gif,png,bmp,jpeg #允许预览文件类型
PreviewType: kkfile #文件预览方式 1.yozo 2.kkfile默认使用kkfile
kkFileUrl: http://127.0.0.1:30090/FileServer/ #kkfile文件预览服务地址
ApiDomain: http://127.0.0.1:30000 #后端域名(文档预览中使用)
FrontDomain: http://127.0.0.1:3100 #前端域名(文档预览中使用)
AppDomain: http://127.0.0.1:8080 #app/h5端域名配置(文档预览中使用)
FlowDomain: http://127.0.0.1:31000 #流程引擎接口地址
CodeAreasName: example #代码生成器模块命名
#===================== unipush =====================
AppPushUrl: https://8e84eea8-6922-4033-8e86-67ad7442e692.bspapp.com/unipush
#===================== 多租户配置 =====================
MultiTenancy: false #是否开启
MultiTenancyUrl: http://127.0.0.1:30006/api/tenant/DbName/ #多租户项目地址
#===================== 系统及错误报告反馈相关 =====================
SoftName: yunzhupaas-java-boot #项目名
SoftFullName: 集团信息化平台 #项目全名
SoftVersion: v5.2.0 #版本号
RecordLog: true #系统日志启用
ErrorReport: false #软件错误报告
ErrorReportTo: surrpot@yunzhupaas.com #软件错误报告接收者
IgexinEnabled: true #推送启动
#===================== APP =====================
AppVersion: v5.2.0 #APP版本号
IgexinAppid: HLFY9T2d1z7MySY8hwGwh4 #APPID应用的唯一标识
IgexinAppkey: 6Uiduugq648YDChhCjAt59 #APPKEY公匙相当于账号
IgexinMastersecret: pEyQm156SJ9iS7PbyjLCZ6 #Mastersecret私匙相当于密码
AppUpdateContent: ; #APP更新内容
#===================== 永中office在线预览配置 =====================
YozoDomain: //dcsapi.com/ #永中api域名
YozoDomainKey: 57462250284462899305150 #域名key
YozoCloudDomain: //dmc.yozocloud.cn #云预览
YozoAppId: yozoAgR41jgC0062 #appid
YozoAppKey: fc3134a9ba8bc6f4c69d635f9adf #app秘钥
YozoEditDomain: //eic.yozocloud.cn #云编辑
#===================== 系统功能配置 =====================
EnableLogicDelete: false #是否开启逻辑删除
CodeCertificateTimeout: 180 # 秒
check-file-pdf: false #检查上传的PDF文件安全
security:
# AES加密秘钥
security-key: EY8WePvjM5GGwQzn
# 是否开启接口鉴权
enable-pre-auth: true
# 接口加密
enable-rest-encrypt: true
# 事件配置
event:
# 默认时间发布、监听渠道: redis, mq
event-publish-type: redis
# Redis监听模式current, all
redis-publish-type: current
# 接口放行地址 与GatewayWhite中的默认URL合并
gateway:
# 禁止访问接口
block-url:
## 配置示例
#- /api/message/Notice
#- /api/permission/Users/*
# 不验证Token, 放行接口(默认记录日志)
white-url:
# # 配置示例
#- /api/message/Notice
#- /api/permission/Users/*
# 放行接口(不记录日志)
exclude-url:
# # 配置示例
#- /api/message/Notice
#- /api/permission/Users/*
# 入站IP禁止配置以外的IP访问block-url配置的接口
white-ip:
#- 192.168.0.10
#- 192.168.0.20
# 日志配置
logging:
config: classpath:logback-spring.xml
level:
#自定义第三方包名日志等级
# 解除注释后Druid连接池打印SQL语句
druid.sql.Statement: debug
# druid.sql.DataSource: debug
# druid.sql.Connection: debug
# druid.sql.ResultSet: debug
log:
level:
# 等级 TRACE,DEBUG,INFO,WARN,ERROR(不区分大小写)
root: info
path: log/${spring.application.name}
mybatis:
mapper-locations: classpath*:com/**/mapper/**/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,335 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--日志格式应用spring boot默认的格式也可以自己更改-->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<property name="FILE_LOG_PATTERN" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] [%logger{50}] [%M] [%line] - %msg%n" />
<springProperty scope="context" name="SERVICE_NAME" source="spring.application.name" defaultValue="yunzhupaas"/>
<!--定义日志存放的位置,默认存放在项目启动的相对路径的目录-->
<springProperty scope="context" name="LOG_PATH" source="log.path" defaultValue="log/${SERVICE_NAME}"/>
<!-- 全局日志等级 -->
<springProperty scope="context" name="LOG_LEVEL_ROOT" source="log.level.root" defaultValue="INFO"/>
<!-- 服务自定义等级 如需自定义服务日志等级 修改下方的【自定义服务名】与nacos上的log.level.自定义服务名=等级 -->
<springProperty scope="context" name="LOG_LEVEL" source="log.level.yunzhupaas-boot" defaultValue="${LOG_LEVEL_ROOT}"/>
<!-- 日志记录器日期滚动记录level为 ERROR 日志 -->
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_error.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd,aux}/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外还配置了日志文件不能超过2M若超过2M日志文件会以索引0开始
命名日志文件例如log-error-2013-12-21.0.log -->
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录error级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器日期滚动记录level为 INFO 日志 -->
<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_info.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd,aux}/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外还配置了日志文件不能超过2M若超过2M日志文件会以索引0开始
命名日志文件例如log-error-2013-12-21.0.log -->
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器日期滚动记录level为 WARN 日志 -->
<appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_warn.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd,aux}/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外还配置了日志文件不能超过2M若超过2M日志文件会以索引0开始
命名日志文件例如log-error-2013-12-21.0.log -->
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器日期滚动记录level为 DEBUG 日志 -->
<appender name="FILE_DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_debug.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd,aux}/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外还配置了日志文件不能超过2M若超过2M日志文件会以索引0开始
命名日志文件例如log-error-2013-12-21.0.log -->
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器,日期滚动记录,所有日志 -->
<appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_total.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/total/%d{yyyy-MM-dd,aux}/log-total-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外还配置了日志文件不能超过2M若超过2M日志文件会以索引0开始
命名日志文件例如log-error-2013-12-21.0.log -->
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!-- 日志记录器日期滚动记录level 根据配置动态输出日志 -->
<appender name="FILE_RELEASE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_release.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/release/%d{yyyy-MM-dd,aux}/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外还配置了日志文件不能超过2M若超过2M日志文件会以索引0开始
命名日志文件例如log-error-2013-12-21.0.log -->
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>${LOG_LEVEL}</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 异步输出 DEBUG -->
<appender name="ASYNC_FILE_DEBUG" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>256</queueSize>
<appender-ref ref="FILE_DEBUG"/>
</appender>
<!-- 异步输出 INFO -->
<appender name="ASYNC_FILE_INFO" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>256</queueSize>
<appender-ref ref="FILE_INFO"/>
</appender>
<!-- 异步输出 WARN -->
<appender name="ASYNC_FILE_WARN" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>256</queueSize>
<appender-ref ref="FILE_WARN"/>
</appender>
<!-- 异步输出 ERROR -->
<appender name="ASYNC_FILE_ERROR" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>256</queueSize>
<appender-ref ref="FILE_ERROR"/>
</appender>
<!-- 异步输出 ALL -->
<appender name="ASYNC_FILE_ALL" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>256</queueSize>
<appender-ref ref="FILE_ALL"/>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!-- 异步输出 控制台 -->
<appender name="ASYNC_STDOUT" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>256</queueSize>
<appender-ref ref="STDOUT"/>
</appender>
<!--<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
&lt;!&ndash; 必填目标LogStash的 IP:Port &ndash;&gt;
<destination>192.168.0.50:50000</destination>
&lt;!&ndash; 可选:保持程序存活时间 &ndash;&gt;
<keepAliveDuration>5 minutes</keepAliveDuration>
&lt;!&ndash; 可选:重连延迟时长 &ndash;&gt;
<reconnectionDelay>10 second</reconnectionDelay>
&lt;!&ndash; 可选:等待策略 &ndash;&gt;
<waitStrategyType>sleeping</waitStrategyType>
&lt;!&ndash; ============ encoder必须配置,有多种可选 ============= &ndash;&gt;
&lt;!&ndash; 编码器二LoggingEventCompositeJsonEncoder &ndash;&gt;
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
&lt;!&ndash; 时间戳:时区 &ndash;&gt;
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
&lt;!&ndash; 模式 &ndash;&gt;
<pattern>
<pattern>
{
"severity": "%level",
"service": "${SERVICE_NAME:-}",
"trace": "%X{X-B3-TraceId:-}",
"span": "%X{X-B3-SpanId:-}",
"exportable": "%X{X-Span-Export:-}",
"pid": "${PID:-}",
"thread": "%thread",
"class": "%logger{40}",
"msg": "%message"
&lt;!&ndash;"idx_pre": "elk-original-third-access",&ndash;&gt;
&lt;!&ndash;"json": "#asJson{%message}" 这个asJson可以把对应的字符串作为json对象取出来这样es可以对json里面的字段索引了&ndash;&gt;
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>-->
<!--<appender name="skywalking-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n</Pattern>
</layout>
</encoder>
</appender>-->
<root level="${LOG_LEVEL}">
<appender-ref ref="ASYNC_STDOUT"/>
<appender-ref ref="ASYNC_FILE_ERROR"/>
<appender-ref ref="ASYNC_FILE_INFO"/>
<appender-ref ref="ASYNC_FILE_WARN"/>
<appender-ref ref="ASYNC_FILE_DEBUG"/>
<appender-ref ref="ASYNC_FILE_ALL"/>
<!--<appender-ref ref="LOGSTASH"/>-->
<!--<appender-ref ref="skywalking-log"/>-->
</root>
</configuration>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mapper.BigDataMapper">
<select id="maxCode" resultType="Integer">
SELECT MAX(F_EN_CODE) FROM ext_big_data
</select>
</mapper>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mapper.FlowFormMapper">
<resultMap id="flowInfo" type="com.yunzhupaas.base.model.flow.FlowTempInfoModel">
<id column="F_Id" property="id"/>
<result column="F_EnCode" property="enCode"/>
</resultMap>
<select id="findFLowInfo" parameterType="String" resultMap="flowInfo">
SELECT ft.F_En_Code as F_EnCode,ft.F_Id as F_Id,F_Enabled_Mark as enabledMark FROM flow_template ft where ft.F_Id =#{tempId}
</select>
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mdm.mapper.CompanyBankMapper">
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mdm.mapper.CompanyInvoiceMapper">
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mdm.mapper.CompanyMapper">
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mdm.mapper.CorporationMapper">
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mdm.mapper.CustomersMapper">
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mdm.mapper.MaterialMapper">
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mdm.mapper.PanyInvoiceMapper">
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mdm.mapper.ProductsMapper">
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mdm.mapper.SupplierMapper">
</mapper>

View File

@@ -0,0 +1,243 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.permission.mapper.AuthorizeMapper">
<resultMap id="ModuleVO" type="com.yunzhupaas.base.model.module.ModuleModel">
<id column="f_id" property="id"/>
<result column="f_parent_id" property="parentId"/>
<result column="f_full_name" property="fullName"/>
<result column="f_en_code" property="enCode"/>
<result column="f_type" property="type"/>
<result column="f_url_address" property="urlAddress"/>
<result column="f_link_target" property="linkTarget"/>
<result column="f_category" property="category"/>
<result column="f_icon" property="icon"/>
<result column="f_sort_code" property="sortCode"/>
<result column="f_property_json" property="propertyJson"/>
<result column="f_system_id" property="systemId"/>
<result column="f_description" property="description"/>
<result column="f_creator_time" property="creatorTimes"/>
</resultMap>
<resultMap id="ButtonVO" type="com.yunzhupaas.base.model.button.ButtonModel">
<id column="f_id" property="id"/>
<result column="f_parent_id" property="parentId"/>
<result column="f_full_name" property="fullName"/>
<result column="f_en_code" property="enCode"/>
<result column="f_icon" property="icon"/>
<result column="f_url_address" property="urlAddress"/>
<result column="f_module_id" property="moduleId"/>
<result column="f_creator_time" property="creatorTimes"/>
<result column="f_sort_code" property="sortCode"/>
</resultMap>
<resultMap id="ColumnVO" type="com.yunzhupaas.base.model.column.ColumnModel">
<id column="f_id" property="id"/>
<result column="f_parent_id" property="parentId"/>
<result column="f_full_name" property="fullName"/>
<result column="f_en_code" property="enCode"/>
<result column="f_bind_table" property="bindTable"/>
<result column="f_bind_table_name" property="bindTableName"/>
<result column="f_module_id" property="moduleId"/>
<result column="f_creator_time" property="creatorTimes"/>
<result column="f_sort_code" property="sortCode"/>
</resultMap>
<resultMap id="ResourceVO" type="com.yunzhupaas.base.model.resource.ResourceModel">
<id column="f_id" property="id"/>
<result column="f_full_name" property="fullName"/>
<result column="f_en_code" property="enCode"/>
<result column="f_condition_json" property="conditionJson"/>
<result column="f_condition_text" property="conditionText"/>
<result column="f_module_id" property="moduleId"/>
<result column="f_match_logic" property="matchLogic"/>
<result column="f_object_id" property="objectId"/>
<result column="f_creator_time" property="creatorTimes"/>
<result column="f_sort_code" property="sortCode"/>
</resultMap>
<resultMap id="FormVO" type="com.yunzhupaas.base.model.form.ModuleFormModel">
<id column="f_id" property="id"/>
<result column="f_parent_id" property="parentId"/>
<result column="f_full_name" property="fullName"/>
<result column="f_en_code" property="enCode"/>
<result column="f_module_id" property="moduleId"/>
<result column="f_creator_time" property="creatorTimes"/>
<result column="f_sort_code" property="sortCode"/>
</resultMap>
<resultMap id="SystemVO" type="com.yunzhupaas.base.model.base.SystemBaeModel">
<id column="f_id" property="id"/>
<result column="f_full_name" property="fullName"/>
<result column="f_en_code" property="enCode"/>
<result column="f_icon" property="icon"/>
<result column="f_property_json" property="propertyJson"/>
<result column="f_description" property="description"/>
<result column="f_sort_code" property="sortCode"/>
<result column="f_enabled_mark" property="enabledMark"/>
<result column="f_workflow_enabled" property="workflowEnabled"/>
<result column="f_navigation_icon" property="navigationIcon"/>
<result column="f_work_logo_icon" property="workLogoIcon"/>
<result column="f_creator_time" property="creatorTimes"/>
</resultMap>
<select id="findModule" parameterType="String" resultMap="ModuleVO">
SELECT * FROM base_module WHERE 1=1
AND (f_id IN
<trim suffixOverrides=" OR f_id IN()">
<foreach collection="objectId" item="id" index="index" open="(" close=")" >
<if test="index != 0">
<choose>
<when test="index % 1000 == 999">) OR f_id IN (</when>
<otherwise>,</otherwise>
</choose>
</if>
#{id}
</foreach>
</trim>
)
<if test="mark == 1">
and f_enabled_mark = #{mark}
</if>
<if test="systemId != null and systemId.size > 0">
and f_system_id in
<foreach collection="systemId" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</if>
and f_en_code not in
<foreach collection="moduleCode" item="urlAddress" open="(" close=")" separator=",">
#{urlAddress}
</foreach>
<if test="moduleAuthorize != null and moduleAuthorize.size > 0">
and f_id not in
<foreach collection="moduleAuthorize" item="moduleId" open="(" close=")" separator=",">
#{moduleId}
</foreach>
</if>
<if test="moduleUrlAddressAuthorize != null and moduleUrlAddressAuthorize.size > 0">
and
((f_url_address not in
<foreach collection="moduleUrlAddressAuthorize" item="urlAddress" open="(" close=")" separator=",">
#{urlAddress}
</foreach>
)
or f_url_address is null
)
</if>
Order by f_sort_code asc,f_creator_time desc
</select>
<select id="findButton" parameterType="String" resultMap="ButtonVO">
SELECT * FROM base_module_button WHERE 1=1
AND (f_id IN
<trim suffixOverrides=" OR f_id IN()">
<foreach collection="objectId" item="id" index="index" open="(" close=")">
<if test="index != 0">
<choose>
<when test="index % 1000 == 999">) OR f_id IN (</when>
<otherwise>,</otherwise>
</choose>
</if>
#{id}
</foreach>
</trim>
)
and f_enabled_mark = 1 Order by f_sort_code asc,f_creator_time desc
</select>
<select id="findColumn" parameterType="String" resultMap="ColumnVO">
SELECT * FROM base_module_column WHERE 1=1
AND (f_id IN
<trim suffixOverrides=" OR f_id IN()">
<foreach collection="objectId" item="id" index="index" open="(" close=")">
<if test="index != 0">
<choose>
<when test="index % 1000 == 999">) OR f_id IN (</when>
<otherwise>,</otherwise>
</choose>
</if>
#{id}
</foreach>
</trim>
)
and f_enabled_mark = 1 Order by f_sort_code asc,f_creator_time desc
</select>
<select id="findForms" parameterType="String" resultMap="FormVO">
SELECT * FROM base_module_form WHERE 1=1
AND (f_id IN
<trim suffixOverrides=" OR f_id IN()">
<foreach collection="objectId" item="id" index="index" open="(" close=")">
<if test="index != 0">
<choose>
<when test="index % 1000 == 999">) OR f_id IN (</when>
<otherwise>,</otherwise>
</choose>
</if>
#{id}
</foreach>
</trim>
)
and f_enabled_mark = 1 Order by f_sort_code asc,f_creator_time desc
</select>
<select id="findSystem" parameterType="String" resultMap="SystemVO">
SELECT * FROM base_system WHERE f_id IN
<foreach collection="objectId" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
<if test="mark == 1">
and f_enabled_mark = #{mark}
</if>
<if test="enCode != null and enCode != ''">
and f_en_code != #{enCode}
</if>
<if test="moduleAuthorize != null and moduleAuthorize.size > 0">
and f_id not in
<foreach collection="moduleAuthorize" item="moduleId" open="(" close=")" separator=",">
#{moduleId}
</foreach>
</if>
Order by f_sort_code asc,f_creator_time desc
</select>
<select id="findResource" parameterType="String" resultMap="ResourceVO">
select s.*, a.f_object_id from base_module_scheme s
LEFT JOIN base_authorize a on s.f_id = a.f_item_id
where 1=1
AND (s.f_id IN
<trim suffixOverrides=" OR s.f_id IN()">
<foreach collection="objectId" item="id" index="index" open="(" close=")">
<if test="index != 0">
<choose>
<when test="index % 1000 == 999">) OR s.f_id IN (</when>
<otherwise>,</otherwise>
</choose>
</if>
#{id}
</foreach>
</trim>
)
and s.f_enabled_mark = 1 Order by s.f_sort_code asc,s.f_creator_time desc
</select>
<select id="findButtonAdmin" parameterType="Integer" resultMap="ButtonVO">
SELECT * FROM base_module_button WHERE f_enabled_mark = #{mark} Order by f_sort_code asc,f_creator_time desc
</select>
<select id="findColumnAdmin" parameterType="Integer" resultMap="ColumnVO">
SELECT * FROM base_module_column WHERE f_enabled_mark = #{mark} Order by f_sort_code asc,f_creator_time desc
</select>
<select id="findFormsAdmin" parameterType="Integer" resultMap="FormVO">
SELECT * FROM base_module_form WHERE f_enabled_mark = #{mark} Order by f_sort_code asc,f_creator_time desc
</select>
<select id="findResourceAdmin" parameterType="Integer" resultMap="ResourceVO">
SELECT * FROM base_module_scheme WHERE f_enabled_mark = #{mark} Order by f_sort_code asc,f_creator_time desc
</select>
</mapper>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.message.mapper.ImContentMapper">
<!-- <update id="SendMessage" parameterType="com.yunzhupaas.system.entity.IMContentEntity">
<id column="F_Id" property="id"/>
<result column="F_SENDUSERID" property="sendUserId"/>
<result column="F_SENDTIME" property="sendTime"/>
<result column="F_RECEIVEUSERID" property="receiveUserId"/>
<result column="F_RECEIVETIME" property="receiveTime"/>
<result column="f_content" property="content"/>
<result column="f_content_type" property="contentType"/>
<result column="F_STATE" property="state"/>
</update>-->
<select id="getUnreadList" parameterType="String" resultType="com.yunzhupaas.message.model.ImUnreadNumModel">
SELECT * FROM (
SELECT SUM(CASE WHEN f_enabled_mark = 0 THEN 1 ELSE 0 END) UnreadNum, f_send_user_id SendUserId, f_receive_user_id ReceiveUserId
FROM base_im_content WHERE 1 = 1 AND f_receive_user_id = #{receiveUserId} GROUP BY f_send_user_id, f_receive_user_id
) t WHERE UnreadNum > 0
</select>
<select id="getUnreadLists" parameterType="String" resultType="com.yunzhupaas.message.model.ImUnreadNumModel">
select f_send_user_id SendUserId, f_content DefaultMessage,f_content_type DefaultMessageType, f_send_time DefaultMessageTime from base_im_content WHERE 1 = 1 AND f_receive_user_id = #{receiveUserId} AND f_enabled_mark = 0 order by f_send_time desc
</select>
<update id="readMessage" parameterType="map">
UPDATE base_im_content SET f_enabled_mark = 1, f_receive_time = #{map.receiveTime} WHERE 1 = 1 AND f_enabled_mark = 0 AND f_send_user_id = #{map.sendUserId} AND f_receive_user_id = #{map.receiveUserId}
</update>
</mapper>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.message.mapper.ImReplyMapper">
<resultMap id="imReplyList" type="com.yunzhupaas.message.model.ImReplyListModel">
<id column="f_receive_user_id" property="id"/>
<result column="f_user_id" property="userId"/>
<result column="F_HEAD_ICON" property="headIcon"/>
<result column="f_receive_time" property="latestDate"/>
<result column="f_content_type" property="messageType"/>
<result column="f_content" property="latestMessage"/>
<result column="f_delete_user_id" property="deleteUserId"/>
<result column="f_delete_mark" property="deleteMark"/>
</resultMap>
<select id="getImReplyList" resultMap="imReplyList" parameterType="com.yunzhupaas.message.model.ImReplyListVo">
SELECT
ir.f_user_id,
ir.f_receive_user_id,
ir.f_delete_user_id,
bu.F_HEAD_ICON,
ir.f_receive_time,
ic.f_content_type,
ic.f_content,
ic.f_delete_user_id,
ic.f_delete_mark
FROM
base_im_reply ir
LEFT JOIN base_user bu ON ir.f_user_id = bu.F_Id
LEFT JOIN base_im_content ic ON ic.f_send_user_id = bu.F_Id
AND ir.f_user_id = ic.f_send_user_id
AND ir.f_receive_user_id = ic.f_receive_user_id
AND ir.f_receive_time = ic.f_send_time
AND (ir.f_delete_mark != 1 OR ir.f_delete_mark IS NULL)
</select>
</mapper>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.message.mapper.MessageMapper">
<resultMap id="Message" type="com.yunzhupaas.message.entity.MessageReceiveEntity">
<id column="f_id" property="id"/>
<result column="f_title" property="title"/>
<result column="f_type" property="type"/>
<result column="f_creator_time" property="creatorTime"/>
<result column="f_creator_user_id" property="creatorUserId"/>
<result column="f_last_modify_time" property="lastModifyTime"/>
<result column="f_enabled_mark" property="enabledMark"/>
<result column="f_is_read" property="isRead"/>
<result column="f_last_modify_user_id" property="lastModifyUserId"/>
</resultMap>
<select id="getMessageList" parameterType="map" resultMap="Message">
SELECT r.f_id, r.f_title, r.f_type, r.f_is_read, r.f_creator_time, r.f_creator_user_id, r.f_last_modify_time, r.f_last_modify_user_id,
u.f_real_name,u.f_account FROM base_message r
LEFT JOIN base_user u ON u.f_id = r.f_user_id where 1 = 1
<if test="map.userId != null">
AND r.f_user_id= #{map.userId}
</if>
<if test="map.keyword != null">
AND (r.f_title like #{map.keyword} OR u.f_real_name LIKE #{map.keyword} OR u.f_account LIKE #{map.keyword})
</if>
<if test="map.type != null">
AND r.f_type = #{map.type}
</if>
<if test="map.isRead != null">
AND r.f_is_read = #{map.isRead}
</if>
ORDER BY r.f_last_modify_time desc
</select>
<select id="getUnreadCount" resultType="int">
SELECT COUNT(1) FROM base_message
WHERE f_user_id = #{userId} AND f_is_read = 0 AND f_type = #{type}
</select>
<select id="getInfoDefault" parameterType="int" resultMap="Message">
SELECT * FROM base_message WHERE 1 = 1 AND f_type = #{type} ORDER BY f_creator_time DESC
</select>
</mapper>

View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.base.mapper.PortalManageMapper">
<sql id="selectPages">
SELECT
<!-- 门户管理表 -->
bpm.f_id id,
bpm.f_enabled_mark enabledMark,
bpm.f_platform platform,
bpm.f_description description,
bpm.F_Tenant_Id tenantId,
bpm.f_sort_code sortCode,
bpm.f_system_id systemId,
bpm.f_portal_id portalId,
bpm.f_creator_time creatorTime,
bpm.f_last_modify_time lastModifyTime,
<!-- 门户表 -->
bp.f_category categoryId,
bp.f_full_name portalName,
bd.f_full_name categoryName,
<!-- 用户表 -->
us.F_Real_Name createUserName,
us.F_Account createUserAccount,
us2.F_Real_Name modifyUserName,
us2.F_Account modifyUserAccount
FROM
base_portal_manage bpm
LEFT JOIN
base_portal bp
ON
bpm.f_portal_id = bp.f_id
LEFT JOIN
base_user us
ON
bpm.F_Creator_User_Id = us.f_id
LEFT JOIN
base_user us2
ON
bpm.F_Last_Modify_User_Id = us2.f_id
LEFT JOIN
base_dictionary_data bd
ON bp.f_category = bd.f_id
WHERE 1 = 1
<if test="pmPage.keyword != null and pmPage.keyword != ''">
AND (bp.f_full_name LIKE #{pmPage.keyword} OR bpm.f_description LIKE #{pmPage.keyword})
</if>
<if test="pmPage.category != null and pmPage.category != ''">
AND
bp.f_category = #{pmPage.category}
</if>
<if test="pmPage.enabledMark != null">
AND
bpm.f_enabled_mark = #{pmPage.enabledMark}
<!-- AND bp.f_enabled_mark = #{pmPage.enabledMark} -->
</if>
<if test="pmPage.platform != null and pmPage.platform != ''">
AND
bpm.f_platform LIKE #{pmPage.platform}
</if>
<if test="pmPage.systemId != null and pmPage.systemId != ''">
AND
bpm.f_system_id = #{pmPage.systemId}
</if>
<if test="pmPage.state != null and pmPage.state != ''">
AND
bp.F_state != #{pmPage.state}
</if>
</sql>
<select id="selectPortalManageDoPage" resultType="com.yunzhupaas.base.model.portalManage.PortalManagePageDO" parameterType="com.yunzhupaas.base.model.portalManage.PortalManagePage">
SELECT
*
FROM (<include refid="selectPages"></include>) TempTable
ORDER BY
sortCode ASC,
creatorTime DESC
</select>
<select id="selectPortalManageDoList" resultType="com.yunzhupaas.base.model.portalManage.PortalManagePageDO" parameterType="com.yunzhupaas.base.model.portalManage.PortalManagePage">
SELECT
*
FROM (<include refid="selectPages"></include>) TempTable
ORDER BY
sortCode ASC,
creatorTime DESC
</select>
<select id="selectPortalBySystemIds" resultType="com.yunzhupaas.base.model.portalManage.PortalManagePageDO" parameterType="java.lang.String">
SELECT
bpm.f_id id,
bpm.f_enabled_mark enabledMark,
bpm.f_platform platform,
bpm.f_description description,
bpm.f_sort_code sortCode,
bpm.f_system_id systemId,
bpm.f_portal_id portalId,
bpm.f_creator_time creatorTime,
bpm.f_last_modify_time lastModifyTime,
bp.f_category categoryId,
bp.f_full_name portalName,
bd.f_full_name categoryName
FROM
base_portal bp
LEFT JOIN base_portal_manage bpm ON bpm.f_portal_id = bp.f_id
LEFT JOIN base_dictionary_data bd ON bp.f_category = bd.f_id
WHERE bpm.f_system_id IN
<foreach collection="systemIds"
item="systemId" index="index" separator="," open="(" close=")">
#{systemId}
</foreach>
<if test="collect != null and collect.size > 0">
AND bpm.f_id IN
<foreach collection="collect"
item="managerId" index="index" separator="," open="(" close=")">
#{managerId}
</foreach>
</if>
AND bpm.f_enabled_mark = 1
ORDER BY
bpm.f_sort_code ASC,
bpm.f_creator_time DESC
</select>
</mapper>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.permission.mapper.PositionMapper">
<select id="getListByUserId" parameterType="String" resultType="com.yunzhupaas.permission.entity.PositionEntity">
SELECT * FROM base_position WHERE F_ID IN(SELECT F_OBJECT_ID FROM base_user_relation WHERE F_USER_ID = #{userId}) ORDER BY F_SORT_CODE
</select>
</mapper>

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.permission.mapper.RoleMapper">
<select id="getListId" resultType="java.lang.String">
SELECT * FROM base_role WHERE F_ID IN(SELECT F_OBJECT_ID FROM base_user_relation WHERE F_USER_ID = #{userId}) ORDER BY F_SORT_CODE
</select>
<select id="query" resultType="java.lang.String">
SELECT F_Id FROM base_role
<if test="globalMark != 1">
WHERE 1 = 1
AND F_Id IN (
SELECT DISTINCT
a.F_Id
FROM
(
SELECT
br.F_Id
FROM
base_organize bo
LEFT JOIN base_organize_relation bor ON bo.F_Id = bor.F_Organize_Id
LEFT JOIN base_role br ON br.F_Id = bor.F_Object_Id
WHERE
bor.F_Object_Type = 'Role'
AND bor.F_Object_Type IS NOT NULL
<if test="orgIdList != null and orgIdList.size() != 0">
AND bo.F_Id IN
<foreach collection="orgIdList"
item="orgIds" index="index" separator="," open="(" close=")">
#{orgIds}
</foreach>
</if>
) a
)
</if>
<if test="globalMark == -1 or globalMark == 1">
<if test="globalMark != 1">
OR
</if>
<if test="globalMark == 1">
Where
</if>
F_Id IN
(
SELECT F_Id FROM base_role WHERE F_Global_Mark = 1
)
</if>
<if test="keyword != null and keyword != ''">
AND (F_Full_Name LIKE #{keyword} OR F_En_Code LIKE #{keyword})
</if>
<if test="enabledMark != null">
AND (f_enabled_Mark = #{enabledMark})
</if>
ORDER BY f_sort_code asc, f_creator_time desc
</select>
<select id="count" resultType="java.lang.Long">
SELECT count(F_Id) FROM base_role
<if test="globalMark != 1">
WHERE 1 = 1
AND F_Id IN (
SELECT DISTINCT
a.F_Id
FROM
(
SELECT
br.F_Id
FROM
base_organize bo
LEFT JOIN base_organize_relation bor ON bo.F_Id = bor.F_Organize_Id
LEFT JOIN base_role br ON br.F_Id = bor.F_Object_Id
WHERE
bor.F_Object_Type = 'Role'
AND bor.F_Object_Type IS NOT NULL
<if test="orgIdList != null and orgIdList.size() != 0">
AND bo.F_Id IN
<foreach collection="orgIdList"
item="orgIds" index="index" separator="," open="(" close=")">
#{orgIds}
</foreach>
</if>
) a
)
</if>
<if test="globalMark == -1 or globalMark == 1">
<if test="globalMark != 1">
OR
</if>
<if test="globalMark == 1">
Where
</if>
F_Id IN
(
SELECT F_Id FROM base_role WHERE F_Global_Mark = 1
)
</if>
<if test="keyword != null and keyword != ''">
AND (F_Full_Name LIKE #{keyword} OR F_En_Code LIKE #{keyword})
</if>
<if test="enabledMark != null">
AND (f_enabled_Mark = #{enabledMark})
</if>
</select>
</mapper>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.base.mapper.SysconfigMapper">
<delete id="deleteFig">
delete from base_sys_config where F_Category ='SysConfig'
</delete>
<delete id="deleteMpFig">
delete from base_sys_config where F_Category='MPConfig'
</delete>
<delete id="deleteQyhFig">
delete from base_sys_config where F_Category='QYHConfig'
</delete>
</mapper>

View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.permission.mapper.UserMapper">
<select id="getListId" resultType="java.lang.String">
SELECT F_Id from base_user WHERE F_Enabled_Mark = 1
</select>
<select id="query" resultType="java.lang.String">
SELECT F_Id FROM
(SELECT DISTINCT u.F_Id,u.F_Sort_Code,u.F_Creator_Time
FROM base_user_relation ul1,base_user u
WHERE u.F_Id = ul1.F_User_Id
AND u.f_account != 'admin'
<if test="enabledMark != null">
AND u.f_enabled_mark = #{enabledMark}
</if>
<if test="gender != null and gender != ''">
AND u.f_gender = #{gender}
</if>
<if test="account != null and account != ''">
and (u.F_Account like #{account} or u.F_Real_Name like #{account} or u.F_Mobile_Phone like
#{account})
</if>
<if test="orgIdList != null and orgIdList.size > 0">
AND (ul1.F_Object_Id IN
<trim suffixOverrides=" OR ul1.F_Object_Id IN()">
<foreach collection="orgIdList" item="orgIds" index="index" open="(" close=")">
<if test="index != 0">
<choose>
<when test="index % 1000 == 999">) OR ul1.F_Object_Id IN (</when>
<otherwise>,</otherwise>
</choose>
</if>
#{orgIds}
</foreach>
</trim>
)
</if>
ORDER BY u.F_Sort_Code ASC,u.F_Creator_Time DESC) uu
</select>
<select id="count" resultType="java.lang.Long">
SELECT count(F_Id) FROM
(SELECT DISTINCT u.F_Id,u.F_Sort_Code,u.F_Creator_Time
FROM base_user_relation ul1,base_user u
WHERE u.F_Id = ul1.F_User_Id
AND u.F_Account != 'admin'
<if test="enabledMark != null">
AND u.f_enabled_mark = #{enabledMark}
</if>
<if test="gender != null and gender != ''">
AND u.f_gender = #{gender}
</if>
<if test="account != null and account != ''">
and (u.F_Account like #{account} or u.F_Real_Name like #{account} or u.F_Mobile_Phone like
#{account})
</if>
<if test="orgIdList != null and orgIdList.size > 0">
AND (ul1.F_Object_Id IN
<trim suffixOverrides=" OR ul1.F_Object_Id IN()">
<foreach collection="orgIdList" item="orgIds" index="index" open="(" close=")">
<if test="index != 0">
<choose>
<when test="index % 1000 == 999">) OR ul1.F_Object_Id IN (</when>
<otherwise>,</otherwise>
</choose>
</if>
#{orgIds}
</foreach>
</trim>
)
</if>) uu
</select>
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mapper.TrainExamRecordsMapper">
</mapper>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mapper.TrainLibraryEssayQuestionMapper">
<select id="getListByParentId" resultType="com.yunzhupaas.entity.TrainLibraryEssayQuestionEntity">
select f_id as id,
f_bank_id as fbankId,
f_full_name as ffullName,
f_answer as fanswer,
f_result as fresult
from make_train_library_essay_question
where f_bank_id = #{parentId}
</select>
<update id="updateResult">
<foreach collection="items" item="item" separator=";">
update make_train_library_essay_question
set f_result = #{item.result}
where f_id = #{item.id}
</foreach>
</update>
</mapper>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mapper.TrainLibraryJudgmentMapper">
<select id="getListByParentId" resultType="com.yunzhupaas.entity.TrainLibraryJudgmentEntity">
select f_id as id,
f_bank_id as fbankId,
f_full_name as ffullName,
f_answer as fanswer
from make_train_library_judgment
where f_bank_id = #{parentId}
</select>
</mapper>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mapper.TrainLibraryMoreMapper">
<select id="getListByParentId" resultType="com.yunzhupaas.entity.TrainLibraryMoreEntity">
select f_id as id,
f_bank_id as fbankId,
f_full_name as ffullName,
f_options_a as foptionsA,
f_options_b as foptionsB,
f_options_c as foptionsC,
f_options_d as foptionsD,
f_answer as fanswer
from make_train_library_more
where f_bank_id = #{parentId}
</select>
</mapper>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mapper.TrainLibrarySingleMapper">
<select id="getListByParentId" resultType="com.yunzhupaas.entity.TrainLibrarySingleEntity">
select f_id as id,
f_bank_id as fbankId,
f_full_name as ffullName,
f_options_a as foptionsA,
f_options_b as foptionsB,
f_options_c as foptionsC,
f_options_d as foptionsD,
f_answer as fanswer
from make_train_library_single
where f_bank_id = #{parentId}
</select>
</mapper>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunzhupaas.mapper.TrainTestPaperLibraryMapper">
<insert id="saveRecords">
INSERT INTO make_train_exam_records
(f_id, f_number,f_library_id, f_examiners, f_full_name, f_sort, f_mark, f_result_score, f_basic_score, f_question_flag,
f_question_status, f_question_score, f_enabled_mark, f_sort_code, f_organize_id, f_creator_time,
f_creator_user_id,f_question_num,f_per_question)
VALUE (#{id}, #{fnumber},#{flibraryId} ,#{fexaminers}, #{ffullName}, #{fsort}, #{fmark}, #{fresultScore}, #{fbasicScore},
#{fquestionFlag},
#{fquestionStatus}, #{fquestionScore}, #{fenabledMark}, #{fsortCode}, #{forganizeId}, #{fcreatorTime},
#{fcreatorUserId},#{fquestionNum},#{fperQuestion})
</insert>
</mapper>

View File

@@ -0,0 +1,52 @@
databaseName: myshardingsphere
dataSources: # 数据源配置 =============
# <数据源_0>: # 自定义数据源名称
# dataSourceClassName: com.zaxxer.hikari.HikariDataSource # 连接池提供方完整类名Spring默认Hikari
# driverClassName: com.mysql.jdbc.Driver # JDBC驱动
# jdbcUrl: jdbc:mysql://{host}:{port}/{dbName}?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8 # 数据库连接URL
# username: {username} # 用户
# password: {password} # 密码
ds0: # 自定义数据源名称
dataSourceClassName: com.alibaba.druid.pool.DruidDataSource # 连接池提供方完整类名Spring默认Hikari
driverClassName: com.mysql.jdbc.Driver # JDBC驱动
url: jdbc:mysql://127.0.0.1:3306/sharding1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8 # 数据库连接URL
username: root # 用户
password: 123456 # 密码
ds1: # 自定义数据源名称
dataSourceClassName: com.alibaba.druid.pool.DruidDataSource # 连接池提供方完整类名Spring默认Hikari
driverClassName: com.mysql.jdbc.Driver # JDBC驱动
url: jdbc:mysql://127.0.0.1:3306/sharding2?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8 # 数据库连接URL
username: root # 用户
password: 123456 # 密码
rules: # 规则 =============
- !SHARDING # 注意类似“- !SHARDING”标识不能省略
tables:
ext_bigdata: # 自定义逻辑表名
actualDataNodes: ds${0..1}.ext_bigdata_$->{0..1} # 由数据源名 + 表名组成(参考 Inline 语法规则)
databaseStrategy:
standard:
shardingColumn: F_Id # 分表依据字段
shardingAlgorithmName: myDataSourceAlgorithm
tableStrategy: # 表策略 -------
standard:
shardingColumn: F_Id # 分表依据字段
shardingAlgorithmName: myTableAlgorithm
# defaultDatabaseStrategy: # 库策略 -------
# standard:
# shardingColumn: F_Id
# shardingAlgorithmName: myDataSourceAlgorithm
shardingAlgorithms: # 分片算法 -------
myDataSourceAlgorithm: # 自定义算法名
type: INLINE
props:
algorithm-expression: ds${(long)(Long.parseLong(F_Id)/10) % 2}
myTableAlgorithm: # 自定义算法名
type: INLINE
props:
algorithm-expression: ext_bigdata_${(long)(Long.parseLong(F_Id)/10 / 2) % 2}
# keyGenerators:
# dsKey: # 自定义主键策略名
# type: SNOWFLAKE
props:
sql-show: true

20
yunzhupaas-app/pom.xml Normal file
View File

@@ -0,0 +1,20 @@
<?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">
<parent>
<artifactId>yunzhupaas-java-boot</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-app</artifactId>
<packaging>pom</packaging>
<modules>
<module>yunzhupaas-app-entity</module>
<module>yunzhupaas-app-biz</module>
<module>yunzhupaas-app-controller</module>
</modules>
</project>

View File

@@ -0,0 +1,35 @@
<?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">
<parent>
<artifactId>yunzhupaas-app</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-app-biz</artifactId>
<dependencies>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-app-entity</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-permission-biz</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-system-biz</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,17 @@
package com.yunzhupaas.mapper;
import com.yunzhupaas.base.mapper.SuperMapper;
import com.yunzhupaas.entity.AppDataEntity;
/**
* app常用数据
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-07-08
*/
public interface AppDataMapper extends SuperMapper<AppDataEntity> {
}

View File

@@ -0,0 +1,57 @@
package com.yunzhupaas.service;
import com.yunzhupaas.base.service.SuperService;
import com.yunzhupaas.entity.AppDataEntity;
import java.util.List;
/**
* app常用数据
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-08-08
*/
public interface AppDataService extends SuperService<AppDataEntity> {
/**
* 列表
*
* @return
*/
List<AppDataEntity> getList();
/**
* 信息
*
* @param objectId 对象主键
* @return
*/
AppDataEntity getInfo(String objectId);
/**
* 验证名称
*
* @param objectId 对象主键
* @return
*/
boolean isExistByObjectId(String objectId, String systemId);
/**
* 创建
*
* @param entity 实体对象
*/
void create(AppDataEntity entity);
/**
* 删除
*
* @param entity 实体对象
*/
void delete(AppDataEntity entity);
}

View File

@@ -0,0 +1,29 @@
package com.yunzhupaas.service;
import com.yunzhupaas.model.AppUserInfoVO;
import com.yunzhupaas.model.AppUsersVO;
/**
* app用户信息
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-08-08
*/
public interface AppService {
/**
* app用户信息
* @return
*/
AppUsersVO userInfo();
/**
* 通讯录
* @return
*/
AppUserInfoVO getInfo(String id);
}

View File

@@ -0,0 +1,72 @@
package com.yunzhupaas.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.base.service.SuperServiceImpl;
import com.yunzhupaas.entity.AppDataEntity;
import com.yunzhupaas.mapper.AppDataMapper;
import com.yunzhupaas.service.AppDataService;
import com.yunzhupaas.util.RandomUtil;
import com.yunzhupaas.util.UserProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* app常用数据
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-08-08
*/
@Service
public class AppDataServiceImpl extends SuperServiceImpl<AppDataMapper, AppDataEntity> implements AppDataService {
@Override
public List<AppDataEntity> getList() {
QueryWrapper<AppDataEntity> queryWrapper = new QueryWrapper<>();
return this.list(queryWrapper);
}
@Override
public AppDataEntity getInfo(String objectId) {
UserInfo userInfo = UserProvider.getUser();
QueryWrapper<AppDataEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(AppDataEntity::getObjectId, objectId).eq(AppDataEntity::getCreatorUserId, userInfo.getUserId());
return this.getOne(queryWrapper);
}
@Override
public boolean isExistByObjectId(String objectId, String systemId) {
UserInfo userInfo = UserProvider.getUser();
QueryWrapper<AppDataEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(AppDataEntity::getObjectId, objectId)
.eq(AppDataEntity::getCreatorUserId, userInfo.getUserId())
.eq(AppDataEntity::getSystemId, systemId);
return this.count(queryWrapper) > 0 ? true : false;
}
@Override
public void create(AppDataEntity entity) {
UserInfo userInfo = UserProvider.getUser();
entity.setId(RandomUtil.uuId());
entity.setCreatorUserId(userInfo.getUserId());
entity.setCreatorTime(new Date());
entity.setEnabledMark(1);
entity.setSystemId(userInfo.getAppSystemId());
this.save(entity);
}
@Override
public void delete(AppDataEntity entity) {
this.removeById(entity.getId());
}
}

View File

@@ -0,0 +1,163 @@
package com.yunzhupaas.service.impl;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.base.entity.DictionaryDataEntity;
import com.yunzhupaas.base.service.DictionaryDataService;
import com.yunzhupaas.model.AppPositionVO;
import com.yunzhupaas.model.AppUserInfoVO;
import com.yunzhupaas.model.AppUsersVO;
import com.yunzhupaas.permission.entity.*;
import com.yunzhupaas.permission.service.*;
import com.yunzhupaas.service.AppService;
import com.yunzhupaas.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* app用户信息
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-08-08
*/
@Service
public class AppServiceImpl implements AppService {
@Autowired
private UserService userService;
@Autowired
private PositionService positionService;
@Autowired
private OrganizeService organizeService;
@Autowired
private RoleService roleService;
@Autowired
private RedisUtil redisUtil;
@Autowired
private UserRelationService userRelationService;
@Autowired
private DictionaryDataService dictionaryDataService;
@Override
public AppUsersVO userInfo() {
UserInfo userInfo = UserProvider.getUser();
UserEntity userEntity = userService.getInfo(userInfo.getUserId());
AppUsersVO usersVO = new AppUsersVO();
usersVO.setBirthday(userEntity.getBirthday() != null ? userEntity.getBirthday().getTime() : null);
usersVO.setEmail(userEntity.getEmail());
List<DictionaryDataEntity> dataServiceList4 = dictionaryDataService.getListByTypeDataCode("sex");
Map<String, String> dataServiceMap4 = dataServiceList4.stream().filter(t -> ObjectUtil.equal(t.getEnabledMark(), 1)).collect(Collectors.toMap(DictionaryDataEntity::getEnCode, DictionaryDataEntity::getFullName));
usersVO.setGender(dataServiceMap4.get(userEntity.getGender()));
usersVO.setMobilePhone(userEntity.getMobilePhone());
this.data(usersVO, userEntity, userInfo);
this.userInfo(usersVO, userInfo);
//岗位
PositionEntity position = positionService.getInfo(userEntity.getPositionId());
AppPositionVO positionVO = new AppPositionVO();
if(position != null){
positionVO.setId(position.getId());
positionVO.setName(position.getFullName());
usersVO.setPositionIds(ListUtil.toList(positionVO));
}
//直属主管
if(StringUtil.isNotEmpty(userEntity.getManagerId())){
UserEntity menager = userService.getInfo(userEntity.getManagerId());
usersVO.setManager(menager != null ? menager.getRealName() + "/" + menager.getAccount() : "");
}
//角色
List<String> roles = roleService.getAllRoleIdsByUserIdAndOrgId(userInfo.getUserId(), usersVO.getOrganizeId());
List<RoleEntity> roleList = roleService.getListByIds(roles, null, false);
usersVO.setRoleName(String.join("", roleList.stream().map(RoleEntity::getFullName).collect(Collectors.toList())));
usersVO.setRoleId(String.join(".", roleList.stream().map(RoleEntity::getId).collect(Collectors.toList())));
return usersVO;
}
@Override
public AppUserInfoVO getInfo(String id) {
AppUserInfoVO userInfoVO = new AppUserInfoVO();
UserEntity entity = userService.getInfo(id);
if (entity != null) {
userInfoVO = JsonUtil.getJsonToBean(entity, AppUserInfoVO.class);
List<String> positionIds = StringUtil.isNotEmpty(entity.getPositionId()) ? Arrays.asList(entity.getPositionId().split(",")) : new ArrayList<>();
List<String> positionName = positionService.getPositionName(positionIds, false).stream().map(t -> t.getFullName()).collect(Collectors.toList());
userInfoVO.setPositionName(String.join(",", positionName));
OrganizeEntity info = organizeService.getInfo(entity.getOrganizeId());
userInfoVO.setOrganizeName(info != null ? info.getFullName() : "");
userInfoVO.setHeadIcon(UploaderUtil.uploaderImg(userInfoVO.getHeadIcon()));
}
return userInfoVO;
}
/**
* 赋值
*
* @param userInfo
* @param userId
* @param isAdmin
*/
private void userInfo(UserInfo userInfo, String userId, boolean isAdmin, UserEntity userEntity) {
List<String> userIdList = new ArrayList(){{add(userId);}};
List<UserRelationEntity> data = userRelationService.getListByUserIdAll(userIdList);
//获取一个字段的值
List<String> positionList = data.stream().filter(m -> "Position".equals(m.getObjectType())).map(t -> t.getObjectId()).collect(Collectors.toList());
Set<String> id = new LinkedHashSet<>();
String[] position = StringUtil.isNotEmpty(userEntity.getPositionId()) ? userEntity.getPositionId().split(",") : new String[]{};
List<String> positions = positionList.stream().filter(t->Arrays.asList(position).contains(t)).collect(Collectors.toList());
id.addAll(positions);
id.addAll(positionList);
userInfo.setPositionIds(id.toArray(new String[id.size()]));
if (!isAdmin) {
data = data.stream().filter(m -> "Role".equals(m.getObjectType())).collect(Collectors.toList());
}
List<String> roleList = data.stream().map(t -> t.getObjectId()).collect(Collectors.toList());
userInfo.setRoleIds(roleList);
}
private void data(AppUsersVO usersVO, UserEntity userEntity, UserInfo userInfo) {
//组织
usersVO.setOrganizeId(userEntity.getOrganizeId());
List<OrganizeEntity> organizeIdList = new ArrayList<>();
organizeService.getOrganizeId(userEntity.getOrganizeId(),organizeIdList);
Collections.reverse(organizeIdList);
usersVO.setOrganizeName(organizeIdList.stream().map(OrganizeEntity::getFullName).collect(Collectors.joining("/")));
OrganizeEntity organizeEntity = organizeIdList.stream().filter(t->t.getId().equals(userEntity.getOrganizeId())).findFirst().orElse(null);
if (organizeEntity != null) {
String[] organizeId = StringUtil.isNotEmpty(organizeEntity.getOrganizeIdTree()) ? organizeEntity.getOrganizeIdTree().split(",") : new String[]{};
if (organizeId.length > 0) {
userInfo.setOrganizeId(organizeId[0]);
userInfo.setDepartmentId(organizeId[organizeId.length - 1]);
}
}
userInfo.setManagerId(userInfo.getManagerId());
boolean b = userInfo.getIsAdministrator();
List<String> subordinateIdsList = userService.getListByManagerId(userInfo.getUserId(),null).stream().map(UserEntity::getId).collect(Collectors.toList());
userInfo.setSubordinateIds(subordinateIdsList);
this.userInfo(userInfo, userInfo.getUserId(), b,userEntity);
// userInfo.setSubOrganizeIds(new String[]{});
//redisUtil.insert(userInfo.getId(), userInfo, DateUtil.getTime(userInfo.getOverdueTime()) - DateUtil.getTime(new Date()));
UserProvider.setLoginUser(userInfo);
UserProvider.setLocalLoginUser(userInfo);
}
/**
* 登录信息
*
* @param appUsersVO 返回对象
* @param userInfo 回话信息
* @return
*/
private void userInfo(AppUsersVO appUsersVO, UserInfo userInfo) {
appUsersVO.setUserId(userInfo.getUserId());
appUsersVO.setHeadIcon(UploaderUtil.uploaderImg(userInfo.getUserIcon()));
appUsersVO.setUserName(userInfo.getUserName());
appUsersVO.setUserAccount(userInfo.getUserAccount());
}
}

View File

@@ -0,0 +1,23 @@
<?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">
<parent>
<artifactId>yunzhupaas-app</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-app-controller</artifactId>
<dependencies>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-app-biz</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,76 @@
package com.yunzhupaas.controller;
import com.yunzhupaas.base.controller.SuperController;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.Operation;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.entity.AppDataEntity;
import com.yunzhupaas.model.AppDataCrForm;
import com.yunzhupaas.service.AppDataService;
import com.yunzhupaas.util.JsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
/**
* app常用数据
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司http://www.szlecheng.cn
* @date 2024-07-08
*/
@Tag(name = "app常用数据", description = "data")
@RestController
@RequestMapping("/api/app/Data")
public class AppDataController extends SuperController<AppDataService, AppDataEntity> {
@Autowired
private AppDataService appDataService;
/**
* 新建
*
* @param appDataCrForm 新建模型
* @return
*/
@PostMapping
@Operation(summary = "新建")
@Parameters({
@Parameter(name = "appDataCrForm", description = "常用模型",required = true),
})
public ActionResult create(@RequestBody @Valid AppDataCrForm appDataCrForm) {
AppDataEntity entity = JsonUtil.getJsonToBean(appDataCrForm, AppDataEntity.class);
if (appDataService.isExistByObjectId(entity.getObjectId(),appDataCrForm.getSystemId())) {
return ActionResult.fail(MsgCode.FA036.get());
}
appDataService.create(entity);
return ActionResult.success(MsgCode.SU001.get());
}
/**
* 删除
*
* @param objectId 主键
* @return
*/
@Operation(summary = "删除")
@DeleteMapping("/{objectId}")
@Parameters({
@Parameter(name = "objectId", description = "主键", required = true),
})
public ActionResult create(@PathVariable("objectId") String objectId) {
AppDataEntity entity = appDataService.getInfo(objectId);
if (entity != null) {
appDataService.delete(entity);
return ActionResult.success(MsgCode.SU003.get());
}
return ActionResult.fail(MsgCode.FA003.get());
}
}

View File

@@ -0,0 +1,96 @@
package com.yunzhupaas.controller;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.base.Page;
import com.yunzhupaas.base.model.module.ModuleModel;
import com.yunzhupaas.base.vo.ListVO;
import com.yunzhupaas.model.AppMenuListVO;
import com.yunzhupaas.model.UserMenuModel;
import com.yunzhupaas.permission.model.authorize.AuthorizeVO;
import com.yunzhupaas.permission.service.AuthorizeService;
import com.yunzhupaas.util.JsonUtil;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.UserProvider;
import com.yunzhupaas.util.treeutil.ListToTreeUtil;
import com.yunzhupaas.util.treeutil.SumTree;
import com.yunzhupaas.util.treeutil.newtreeutil.TreeDotUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.*;
import java.util.stream.Collectors;
/**
* app应用
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司http://www.szlecheng.cn
* @date 2024-07-08
*/
@Tag(name = "app应用", description = "Menu")
@RestController
@RequestMapping("/api/app/Menu")
public class AppMenuController {
@Autowired
private AuthorizeService authorizeService;
/**
* 获取菜单列表
*
* @param page 分页模型
* @return
*/
@Operation(summary = "获取菜单列表")
@GetMapping
public ActionResult<ListVO<AppMenuListVO>> list(Page page) {
AuthorizeVO authorizeModel = authorizeService.getAuthorize(false, false);
List<ModuleModel> buttonListAll = authorizeModel.getModuleList().stream().filter(t -> "App".equals(t.getCategory())).collect(Collectors.toList());
// 通过系统id捞取相应的菜单
buttonListAll = buttonListAll.stream().filter(t -> UserProvider.getUser().getAppSystemId() != null && UserProvider.getUser().getAppSystemId().equals(t.getSystemId())).collect(Collectors.toList());
List<ModuleModel> buttonList = buttonListAll;
if (StringUtil.isNotEmpty(page.getKeyword())) {
buttonList = buttonListAll.stream().filter(t -> t.getFullName().contains(page.getKeyword())).collect(Collectors.toList());
}
List<UserMenuModel> list = JsonUtil.getJsonToList(ListToTreeUtil.treeWhere(buttonList, buttonListAll), UserMenuModel.class);
List<SumTree<UserMenuModel>> menuAll = TreeDotUtils.convertListToTreeDot(list, "-1");
List<AppMenuListVO> data = JsonUtil.getJsonToList(menuAll, AppMenuListVO.class);
ListVO listVO = new ListVO();
listVO.setList(data);
return ActionResult.success(listVO);
}
/**
* 获取子集菜单
*
* @return
*/
@Operation(summary = "获取子集菜单")
@GetMapping("/getChildList/{id}")
public ActionResult<List<AppMenuListVO>> getChildList(@PathVariable("id") String id) {
AuthorizeVO authorizeModel = authorizeService.getAuthorize(false, false);
List<ModuleModel> buttonListAll = authorizeModel.getModuleList().stream().filter(t -> "App".equals(t.getCategory())).collect(Collectors.toList());
// 通过系统id捞取相应的菜单
buttonListAll = buttonListAll.stream().filter(t -> UserProvider.getUser().getAppSystemId() != null && UserProvider.getUser().getAppSystemId().equals(t.getSystemId())).collect(Collectors.toList());
Set<ModuleModel> models = new HashSet<>();
next(buttonListAll,id,models);
List<UserMenuModel> list = JsonUtil.getJsonToList(models, UserMenuModel.class);
List<SumTree<UserMenuModel>> menuAll = TreeDotUtils.convertListToTreeDot(list);
List<AppMenuListVO> data = JsonUtil.getJsonToList(menuAll, AppMenuListVO.class);
return ActionResult.success(data);
}
private void next(List<ModuleModel> buttonListAll,String parentId,Set<ModuleModel> list){
List<ModuleModel> menuList = buttonListAll.stream().filter(t -> t.getId().equals(parentId) || t.getParentId().equals(parentId)).collect(Collectors.toList());
for (ModuleModel model : menuList) {
if(!list.contains(model)){
list.add(model);
next(buttonListAll,model.getId(),list);
}
}
}
}

View File

@@ -0,0 +1,62 @@
package com.yunzhupaas.controller;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.Operation;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.model.AppUserInfoVO;
import com.yunzhupaas.model.AppUsersVO;
import com.yunzhupaas.service.AppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用户信息
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司http://www.szlecheng.cn
* @date 2024-07-08
*/
@Tag(name = "app用户信息", description = "User")
@RestController
@RequestMapping("/api/app/User")
public class AppUserController {
@Autowired
private AppService appService;
/**
* 用户信息
*
* @return
*/
@Operation(summary = "用户信息")
@GetMapping
public ActionResult<AppUsersVO> getInfo() {
AppUsersVO userAllVO = appService.userInfo();
return ActionResult.success(userAllVO);
}
/**
* 通讯录详情
*
* @param id 主键
* @return
*/
@Operation(summary = "通讯录详情")
@GetMapping("/{id}")
@Parameters({
@Parameter(name = "id", description = "主键", required = true),
})
public ActionResult<AppUserInfoVO> userInfo(@PathVariable("id") String id) {
AppUserInfoVO userInfoVO = appService.getInfo(id);
return ActionResult.success(userInfoVO);
}
}

View File

@@ -0,0 +1,45 @@
package com.yunzhupaas.controller;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.config.ConfigValueUtil;
import com.yunzhupaas.util.NoDataSourceBind;
import org.apache.commons.collections4.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* 获取AppVersion
*
* @author :云筑产品开发平台组
* @version: V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2022/3/31 11:26
*/
@Tag(name = "获取APP版本号", description = "AppVersion")
@RestController
@RequestMapping("/api/app")
public class AppVersionController {
@Autowired
private ConfigValueUtil configValueUtil;
/**
* 判断是否需要验证码
*
* @return
*/
@NoDataSourceBind()
@Operation(summary = "判断是否需要验证码")
@GetMapping("/Version")
public ActionResult getAppVersion() {
Map<String, String> map = new HashedMap<>();
map.put("sysVersion", configValueUtil.getAppVersion());
return ActionResult.success(map);
}
}

View File

@@ -0,0 +1,22 @@
<?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">
<parent>
<artifactId>yunzhupaas-app</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-app-entity</artifactId>
<dependencies>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-common-all</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,47 @@
package com.yunzhupaas.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.yunzhupaas.base.entity.SuperExtendEntity;
import lombok.Data;
import java.util.Date;
/**
* app常用数据
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-08-08
*/
@Data
@TableName("base_app_data")
public class AppDataEntity extends SuperExtendEntity.SuperExtendDEEntity<String> {
/**
* 对象类型
*/
@TableField("f_object_type")
private String objectType;
/**
* 对象主键
*/
@TableField("f_object_id")
private String objectId;
/**
* 数据
*/
@TableField("f_object_data")
private String objectData;
/**
* 关联系统id
*/
@TableField("f_system_id")
private String systemId;
}

View File

@@ -0,0 +1,31 @@
package com.yunzhupaas.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
/**
* app常用数据
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-07-08
*/
@Data
@Schema(description = "常用模型")
public class AppDataCrForm {
@NotBlank(message = "必填")
@Schema(description = "应用类型")
private String objectType;
@NotBlank(message = "必填")
@Schema(description = "应用主键")
private String objectId;
@Schema(description = "数据")
private String objectData;
@Schema(description = "系统主键")
private String systemId;
}

View File

@@ -0,0 +1,47 @@
package com.yunzhupaas.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* app常用数据
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-07-08
*/
@Data
@Schema(description = "常用模型")
public class AppDataListAllVO {
@Schema(description = "主键")
private String id;
@Schema(description = "是否有下级菜单")
private Boolean hasChildren;
@Schema(description = "菜单名称")
private String fullName;
@Schema(description = " 图标")
private String icon;
@Schema(description = "链接地址")
private String urlAddress;
@Schema(description = "父级id")
private String parentId;
@Schema(description = "菜单类型",example = "1")
private Integer type;
@Schema(description = "扩展字段")
private String propertyJson;
@Schema(description = "图标背景色")
private String iconBackground;
@Schema(description = "是否常用")
private Boolean isData;
@Schema(description = "排序")
private Long sortCode;
@Schema(description = "分类")
private String category;
@Schema(description = "下级菜单列表")
private List<AppDataListAllVO> children;
}

View File

@@ -0,0 +1,25 @@
package com.yunzhupaas.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* app常用数据
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-07-08
*/
@Data
@Schema(description = "常用模型")
public class AppDataListVO {
@Schema(description = "主键")
private String id;
@Schema(description = "应用主键")
private String objectId;
@Schema(description = "数据")
private String objectData;
}

View File

@@ -0,0 +1,31 @@
package com.yunzhupaas.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* app常用数据
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-07-08
*/
@Data
@Schema(description = "常用模型")
public class AppFlowListAllVO {
@Schema(description = "主键")
private String id;
@Schema(description = "名称")
private String fullName;
@Schema(description = "图标")
private String icon;
@Schema(description = "图标背景色")
private String iconBackground;
@Schema(description = "编码")
private String enCode;
@Schema(description = "是否常用")
private Boolean isData;
}

View File

@@ -0,0 +1,43 @@
package com.yunzhupaas.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* app应用
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-07-08
*/
@Data
@Schema(description = "常用模型")
public class AppMenuListVO {
@Schema(description = "主键")
private String id;
@Schema(description = "是否有下级菜单")
private Boolean hasChildren;
@Schema(description = "父级id")
private String parentId;
@Schema(description = "菜单编码")
private String enCode;
@Schema(description = "菜单名称")
private String fullName;
@Schema(description = " 图标")
private String icon;
@Schema(description = "是否常用")
private Boolean isData;
@Schema(description = "链接地址")
private String urlAddress;
@Schema(description = "菜单类型",example = "1")
private Integer type;
@Schema(description = "扩展字段")
private String propertyJson;
@Schema(description = "下级菜单列表")
private List<AppMenuListVO> children;
}

View File

@@ -0,0 +1,23 @@
package com.yunzhupaas.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* app应用
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-08-08
*/
@Data
@Schema(description = "常用模型")
public class AppPositionVO {
@Schema(description = "岗位id")
private String id;
@Schema(description = "岗位名称")
private String name;
}

View File

@@ -0,0 +1,38 @@
package com.yunzhupaas.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/12 15:31
*/
@Data
@Schema(description = "常用模型")
public class AppUserInfoVO {
@Schema(description = "主键")
private String id;
@Schema(description = "户名")
private String realName;
@Schema(description = "部门名称")
private String organizeName;
@Schema(description = "账号")
private String account;
@Schema(description = "岗位名称")
private String positionName;
@Schema(description = "办公电话")
private String telePhone;
@Schema(description = "办公座机")
private String landline;
@Schema(description = "手机号码")
private String mobilePhone;
@Schema(description = "用户头像")
private String headIcon;
@Schema(description = "邮箱")
private String email;
}

View File

@@ -0,0 +1,51 @@
package com.yunzhupaas.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* 用户
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-07-08
*/
@Data
@Schema(description = "常用模型")
public class AppUsersVO {
@Schema(description = "用户id")
private String userId;
@Schema(description = "用户账号")
private String userAccount;
@Schema(description = "用户姓名")
private String userName;
@Schema(description = "用户头像")
private String headIcon;
@Schema(description = "组织主键")
private String organizeId;
@Schema(description = "组织名称")
private String organizeName;
@Schema(description = "角色主键")
private String roleId;
@Schema(description = "角色名称")
private String roleName;
@Schema(description = "性别")
private String gender;
@Schema(description = "岗位")
private List<AppPositionVO> positionIds;
@Schema(description = "生日")
private Long birthday;
@Schema(description = "手机")
private String mobilePhone;
@Schema(description = "邮箱")
private String email;
@Schema(description = "直属主管")
private String manager;
}

50
yunzhupaas-crm/pom.xml Normal file
View File

@@ -0,0 +1,50 @@
<?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">
<parent>
<artifactId>yunzhupaas-java-boot</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-crm</artifactId>
<packaging>pom</packaging>
<modules>
<module>yunzhupaas-crm-entity</module>
<module>yunzhupaas-crm-biz</module>
<module>yunzhupaas-crm-controller</module>
</modules>
<dependencies>
<!-- Apache POI dependencies -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>3.1.0</version>
</dependency>
<!-- Apache POI dependencies for OOXML (.docx) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
<!-- Apache POI dependencies for OLE2 (.doc) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.2</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,31 @@
<?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">
<parent>
<artifactId>yunzhupaas-crm</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-crm-biz</artifactId>
<dependencies>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-crm-entity</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-generater-base</artifactId>
<version>5.2.0-RELEASE</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,23 @@
<?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">
<parent>
<artifactId>yunzhupaas-crm</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-crm-controller</artifactId>
<dependencies>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-crm-biz</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,22 @@
<?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">
<parent>
<artifactId>yunzhupaas-crm</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-crm-entity</artifactId>
<dependencies>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-common-all</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,20 @@
<?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">
<parent>
<artifactId>yunzhupaas-java-boot</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-example</artifactId>
<packaging>pom</packaging>
<modules>
<module>yunzhupaas-example-entity</module>
<module>yunzhupaas-example-biz</module>
<module>yunzhupaas-example-controller</module>
</modules>
</project>

View File

@@ -0,0 +1,27 @@
<?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">
<parent>
<artifactId>yunzhupaas-example</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-example-biz</artifactId>
<dependencies>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-example-entity</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-generater-base</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,17 @@
package com.yunzhupaas.mapper;
import com.yunzhupaas.base.mapper.SuperMapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yunzhupaas.entity.ContractEntity;
/**
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/16 9:47
*/
public interface ContractMapper extends SuperMapper<ContractEntity> {
}

View File

@@ -0,0 +1,29 @@
package com.yunzhupaas.service;
import com.yunzhupaas.base.service.SuperService;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yunzhupaas.base.Pagination;
import com.yunzhupaas.entity.ContractEntity;
import java.util.List;
/**
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/16 9:47
*/
public interface ContractService extends SuperService<ContractEntity> {
List<ContractEntity> getlist(Pagination pagination);
ContractEntity getInfo(String id);
void create(ContractEntity entity);
void update(String id, ContractEntity entity);
void delete(ContractEntity entity);
}

View File

@@ -0,0 +1,81 @@
package com.yunzhupaas.service.impl;
import com.yunzhupaas.base.service.SuperServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunzhupaas.base.Pagination;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.mapper.ContractMapper;
import com.yunzhupaas.service.ContractService;
import com.yunzhupaas.entity.ContractEntity;
import com.yunzhupaas.util.RandomUtil;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.UserProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import java.util.List;
/**
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/16 9:47
*/
@Service
public class ContractServiceImpl extends SuperServiceImpl<ContractMapper, ContractEntity> implements ContractService {
@Override
public List<ContractEntity> getlist(Pagination pagination){
//通过UserProvider获取用户信息
QueryWrapper<ContractEntity> queryWrapper = new QueryWrapper<>();
if (!StringUtil.isEmpty(pagination.getKeyword())) {
queryWrapper.lambda().and(
t -> t.like(ContractEntity::getContractName, pagination.getKeyword())
.or().like(ContractEntity::getMytelePhone, pagination.getKeyword())
);
}
//排序
if (StringUtil.isEmpty(pagination.getSidx())) {
} else {
queryWrapper = "asc".equals(pagination.getSort().toLowerCase()) ? queryWrapper.orderByAsc(pagination.getSidx()) : queryWrapper.orderByDesc(pagination.getSidx());
}
Page<ContractEntity> page = new Page<>(pagination.getCurrentPage(), pagination.getPageSize());
IPage<ContractEntity> userPage = this.page(page, queryWrapper);
return pagination.setData(userPage.getRecords(), page.getTotal());
}
@Override
public ContractEntity getInfo(String id){
QueryWrapper<ContractEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(ContractEntity::getId, id);
return this.getOne(queryWrapper);
}
@Override
@DSTransactional
public void create(ContractEntity entity){
entity.setId(RandomUtil.uuId());
this.save(entity);
}
@Override
@DSTransactional
public void update(String id, ContractEntity entity){
entity.setId(id);
this.updateById(entity);
}
@Override
public void delete(ContractEntity entity) {
if (entity != null) {
this.removeById(entity.getId());
}
}
}

View File

@@ -0,0 +1,22 @@
<?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">
<parent>
<artifactId>yunzhupaas-example</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-example-controller</artifactId>
<dependencies>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-example-biz</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,125 @@
package com.yunzhupaas.controller;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.Operation;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.base.Pagination;
import com.yunzhupaas.base.controller.SuperController;
import com.yunzhupaas.base.vo.PageListVO;
import com.yunzhupaas.base.vo.PaginationVO;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.entity.ContractEntity;
import com.yunzhupaas.model.ContractForm;
import com.yunzhupaas.model.ContractInfoVO;
import com.yunzhupaas.model.ContractListVO;
import com.yunzhupaas.service.ContractService;
import com.yunzhupaas.util.JsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import java.util.List;
/**
* Contract
* 版本: V3.0.0
* 版权: 深圳市乐程软件有限公司(http://www.szlecheng.cn)
* 作者: 云筑产品开发平台组
* 日期: 2020-12-31
*/
@RestController
@Tag(name = "示例接口", description = "Contract")
@RequestMapping("/Contract")
public class ContractController extends SuperController<ContractService, ContractEntity> {
@Autowired
private ContractService contractService;
/**
* 获取列表
*
* @param pagination 分页模型
* @return
*/
@Operation(summary = "获取列表")
@GetMapping("/List")
public ActionResult<PageListVO<ContractListVO>> list(Pagination pagination) {
List<ContractEntity> entity = contractService.getlist(pagination);
List<ContractListVO> listVo = JsonUtil.getJsonToList(JsonUtil.getObjectToStringDateFormat(entity, "yyyy-MM-dd HH:mm:ss"), ContractListVO.class);
PaginationVO vo = JsonUtil.getJsonToBean(pagination, PaginationVO.class);
return ActionResult.page(listVo, vo);
}
/**
* 获取详情
*
* @param id 主键
* @return
*/
@Operation(summary = "获取详情")
@GetMapping("/{id}")
@Parameters({
@Parameter(name = "id", description = "主键", required = true),
})
public ActionResult<ContractInfoVO> info(@PathVariable("id") String id) {
ContractEntity entity = contractService.getInfo(id);
ContractInfoVO vo = JsonUtil.getJsonToBean(entity, ContractInfoVO.class);
return ActionResult.success(vo);
}
/**
* 新建
*
* @param contractForm 新建模型
* @return
*/
@Operation(summary = "新建")
@PostMapping
@Parameters({
@Parameter(name = "contractForm", description = "示例模型",required = true),
})
public ActionResult create(@RequestBody @Valid ContractForm contractForm) {
ContractEntity entity = JsonUtil.getJsonToBean(contractForm, ContractEntity.class);
contractService.create(entity);
return ActionResult.success(MsgCode.SU002.get());
}
/**
* @param id 主键
* @param contractForm 修改模型
* @return
*/
@Operation(summary = "修改")
@PutMapping("/{id}")
@Parameters({
@Parameter(name = "contractForm", description = "示例模型",required = true),
@Parameter(name = "id", description = "主键", required = true),
})
public ActionResult update(@PathVariable("id") String id, @RequestBody @Valid ContractForm contractForm) {
ContractEntity entity = JsonUtil.getJsonToBean(contractForm, ContractEntity.class);
contractService.update(id, entity);
return ActionResult.success(MsgCode.SU004.get());
}
/**
* 删除
*
* @param id 主键
* @return
*/
@Operation(summary = "删除")
@DeleteMapping("/{id}")
@Parameters({
@Parameter(name = "id", description = "主键", required = true),
})
public ActionResult delete(@PathVariable("id") String id) {
ContractEntity entity = contractService.getInfo(id);
contractService.delete(entity);
return ActionResult.success(MsgCode.SU003.get());
}
}

View File

@@ -0,0 +1,22 @@
<?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">
<parent>
<artifactId>yunzhupaas-example</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-example-entity</artifactId>
<dependencies>
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-common-all</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,34 @@
package com.yunzhupaas.entity;
import com.yunzhupaas.base.entity.SuperBaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
/**
*
* Contract
* 版本: V3.0.0
* 版权: 深圳市乐程软件有限公司(http://www.szlecheng.cn)
* 作者: 云筑产品开发平台组
* 日期: 2020-12-31
*/
@Data
@TableName("test_contract")
public class ContractEntity extends SuperBaseEntity.SuperTBaseEntity<String> implements Serializable {
@TableField("F_CONTRACTNAME")
private String contractName;
@TableField("F_MYTELEPHONE")
private String mytelePhone;
@TableField("F_FILEJSON")
private String fileJson;
}

View File

@@ -0,0 +1,27 @@
package com.yunzhupaas.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
*
*
* 版本: V3.0.0
* 版权: 深圳市乐程软件有限公司(http://www.szlecheng.cn)
* 作者: 云筑产品开发平台组
* 日期: 2020-12-31
*/
@Data
public class ContractForm {
@Schema(description = "姓名")
private String contractName;
@Schema(description = "手机号")
private String mytelePhone;
@Schema(description = "文件")
private String fileJson;
}

View File

@@ -0,0 +1,28 @@
package com.yunzhupaas.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
*
*
* 版本: V3.0.0
* 版权: 深圳市乐程软件有限公司(http://www.szlecheng.cn)
* 作者: 云筑产品开发平台组
* 日期: 2020-12-31
*/
@Data
public class ContractInfoVO {
@Schema(description = "主键")
private String id;
@Schema(description = "姓名")
private String contractName;
@Schema(description = "手机号")
private String mytelePhone;
@Schema(description = "文件")
private String fileJson;
}

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