chore: import Java_DmK project

This commit is contained in:
czc
2026-07-03 16:23:51 +08:00
commit 538b4931dd
200 changed files with 74913 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
target/
*.rar
JavaAPP.jar
hs_err_pid*.log
.idea/
application-local.properties
application-prod.properties
WebErp/weberp/src/main/resources/application-local.properties
WebErp/weberp/src/main/resources/application-prod.properties
Binary file not shown.
+356
View File
@@ -0,0 +1,356 @@
# 产品源代码整体架构说明
本文档基于当前仓库代码结构整理,用于快速理解 LSERP-MES / WebErp 后端工程的模块边界、请求调用链、数据访问方式和主要扩展点。
## 1. 工程概览
本项目是一个基于 Spring Boot 的 Java 后端服务,代码主体位于 `WebErp/weberp`。整体采用 Maven 父子模块结构,当前父工程 `WebErp` 下只有一个可执行子模块 `weberp`
| 层级 | 路径 | 说明 |
| --- | --- | --- |
| 仓库根目录 | `.` | README、历史构建产物和项目根文件 |
| Maven 父工程 | `WebErp/pom.xml` | `packaging=pom`,聚合 `weberp` 子模块,统一部分依赖版本 |
| 应用子模块 | `WebErp/weberp` | Spring Boot 可执行 JAR 模块,主类为 `org.example.WebErpApplication` |
| 主源码 | `WebErp/weberp/src/main/java/org/example` | Controller、Handler、Impl、Entity、Utils 等后端源码 |
| 配置资源 | `WebErp/weberp/src/main/resources` | `application.properties`、MyBatis 配置、Mapper XML、语言包 |
| 测试代码 | `WebErp/weberp/src/test/java/org/example` | 单元/回归测试入口 |
关键技术栈:
- Spring Boot Web 3.4.3HTTP 服务和依赖注入。
- Spring Security 3.4.3:接口访问控制。
- MyBatis 3.5.17 / mybatis-spring-boot-starter 3.0.4Mapper XML 数据访问。
- JdbcTemplate / NamedParameterJdbcTemplate:大量动态 SQL 和存储过程调用。
- HikariCP:数据库连接池。
- PageHelper:分页插件,当前方言配置为 `dm`
- JJWT:Token 生成、刷新和校验辅助。
- Redis:缓存或会话相关基础设施。
- Aspose / Spire / iText / JavaCV / ZXingOffice、PDF、音视频、二维码等文件处理能力。
## 2. 总体架构图
```mermaid
flowchart TB
Client["Web / App / 桌面前端"]
subgraph SpringBoot["Spring Boot 应用: weberp"]
App["WebErpApplication"]
Security["SecurityConfig<br/>允许 /Api/* 指定入口"]
Cors["CorsConfig<br/>跨域和凭证配置"]
subgraph Entry["统一 API 入口层"]
AuthCtrl["AuthController<br/>/Api/SysUserAjaxApi"]
ModuleCtrl["ModuleAjaxController<br/>/Api/ModuleAjaxApi"]
SystemCtrl["SystemAjaxApi<br/>/Api/SystemAjaxApi"]
FileCtrl["FileUploadController<br/>/Api/FileUploadApi"]
ToolsCtrl["ToolsHandler<br/>/Api/ToolsHandler"]
end
subgraph Handler["公共请求处理层"]
BaseHandler["BaseHandler<br/>method/action 反射分发<br/>登录校验 / 参数校验 / 响应输出"]
OptBaseHandler["OptBaseHandler<br/>注入 JdbcTemplate / Mapper / SQL Factory"]
RequestHandler["RequestHandler<br/>普通参数 / pms / gzip 参数解析"]
end
subgraph ServiceImpl["业务服务与实现层"]
ModuleService["ModuleImplService"]
AuthService["AuthService"]
ModuleImpl["ModuleImpl<br/>模块配置 / 数据 / 审核 / 桌面"]
DataImpl["DataImpl<br/>动态 SQL / 表结构 / 存储过程"]
SysUserImpl["SysUserImpl<br/>登录 / 用户 / 账套"]
SystemImpl["SystemImpl<br/>系统菜单 / 系统信息"]
FileImpl["FileImpl<br/>文件与附件"]
MapImpl["MapImpl<br/>区域地图"]
UpdateImpl["UpdateImpl<br/>系统更新脚本"]
end
subgraph Domain["领域模型和工具层"]
Entity["Entity<br/>BaseResponse / Module / Bill / Control / Audit"]
Utils["Utils<br/>DbOperator / JSON / Cache / JwtHelp / FileUtil / WebConfig"]
Office["Office<br/>文档处理"]
end
subgraph DataAccess["数据访问层"]
Factory["AllInOneSqlFactory"]
Provider["AllInOneSqlProvider<br/>dm / kingbase 实现"]
Mappers["MyBatis Mapper<br/>CRMapper / DMCrmMapper / PageBreaksMapper"]
Xml["resources/mapper/*.xml"]
Jdbc["JdbcTemplate<br/>NamedParameterJdbcTemplate"]
end
end
DB[("业务数据库<br/>达梦 / 人大金仓 / SQL Server / MySQL 驱动")]
Redis[("Redis")]
FileStore[("文件存储目录")]
Client --> Security
Security --> Cors
Cors --> Entry
Entry --> BaseHandler
BaseHandler --> OptBaseHandler
BaseHandler --> RequestHandler
OptBaseHandler --> ServiceImpl
ServiceImpl --> Domain
ServiceImpl --> Factory
Factory --> Provider
Provider --> Mappers
Mappers --> Xml
ServiceImpl --> Jdbc
Mappers --> DB
Jdbc --> DB
Utils --> Redis
FileImpl --> FileStore
Office --> FileStore
```
## 3. 请求处理架构
项目的 HTTP 入口不是标准的“一个 URL 对应一个业务方法”的 REST 风格,而是多个 Ajax 入口统一接收请求,再由 `BaseHandler` 根据请求参数中的 `method``action` 反射调用同名业务方法。
```mermaid
sequenceDiagram
participant C as 前端
participant Ctrl as Ajax Controller
participant BH as BaseHandler
participant BI as OptBaseImpl/BaseImpl
participant Impl as 业务 Impl
participant DB as 数据库
C->>Ctrl: GET/POST /Api/ModuleAjaxApi?method=GetModuleData
Ctrl->>BH: processRequest(request)
BH->>BI: initSystemParams / initReqPms
BH->>BH: 读取 method/action
BH->>BH: 查找同名 public 方法
BH->>BH: 读取 @RequestCheck
BH->>BI: 登录校验 / 参数校验 / 当前用户上下文
BH->>Impl: 反射调用业务方法
Impl->>DB: Mapper 或 JdbcTemplate 查询/更新
DB-->>Impl: 数据结果
Impl-->>BH: BaseResponse
BH-->>C: text/plain;charset=UTF-8 JSON 响应
```
主要机制:
- `Controller` 只提供统一入口,例如 `/Api/ModuleAjaxApi/**``/Api/SystemAjaxApi/**``/Api/SysUserAjaxApi/**`
- `BaseHandler#getMethod()``method``action` 参数获取业务方法名。
- `BaseHandler#processRequest()` 负责参数初始化、登录检查、`@RequestCheck` 校验、缓存判断、反射调用、日志记录、Token 刷新和响应输出。
- `RequestHandler` 兼容普通 query/form 参数、`pms` 加密参数、gzip/deflate 压缩请求体。
- `OptBaseHandler``BaseHandler` 基础上注入 `JdbcTemplate``CRMapper``DMCrmMapper``AllInOneSqlFactory`,并创建 `OptBaseImpl` 作为业务上下文。
## 4. 源码包职责
| 包 | 主要职责 |
| --- | --- |
| `org.example` | Spring Boot 启动入口 `WebErpApplication` |
| `Api` | 公共请求处理、统一响应、登录状态、日志、单用户控制 |
| `Auth` | 登录、验证码、密码、Token、安全辅助 |
| `Config` | CORS 配置 |
| `SystemApi` | 系统信息、系统菜单、账套/系统版本等接口 |
| `ModuleApi` | 核心模块 Ajax 接口、模块 DTO、MyBatis Mapper |
| `FileUploadApi` | 文件上传、下载、附件权限与附件记录维护 |
| `Impl` | 主要业务实现层,包含模块、数据、用户、系统、文件、地图、短信、更新等实现 |
| `Impl.Sql` | 多数据库 SQL Provider 和工厂,按数据库类型生成 SQL 或调用对应 Mapper |
| `Service` | 业务接口定义,例如 `ModuleImplService``AuthService``IModuleEvent` |
| `Entity` | 响应对象、模块配置对象、单据对象、控件对象、审核对象、异常对象等领域模型 |
| `Enums` | 系统枚举、参数方向、任务类型、登录状态等 |
| `Utils` | 通用工具,包括配置读取、JSON、缓存、JWT、文件、压缩、加密、数据库操作等 |
| `Office` | Office/Word 文档生成与转换相关工具 |
| `PageBreaksApi` | 分页符相关 Mapper |
## 5. 核心业务模块
### 5.1 认证与用户
入口:`AuthController`,路径为 `/Api/SysUserAjaxApi`
核心实现:
- `SysUserImpl implements AuthService`:登录、手机号登录、切换账套、重置密码、验证码、登录状态维护。
- `JwtHelp` / `JwtUtils`:Token 创建、刷新、缓存和解析辅助。
- `SingleUserHandler`:单用户登录控制和会话互斥。
- `SafetyUtil`:安全辅助逻辑。
典型方法:
- `Login`
- `CheckLogin`
- `LoginOut`
- `ChangeServer`
- `ResetPwd`
- `GenerateCaptcha`
- `SendPhoneCode`
### 5.2 系统基础信息
入口:`SystemAjaxApi`,路径为 `/Api/SystemAjaxApi`
核心实现:
- `SystemImpl`:系统列表、系统信息、登录信息、菜单、数据库服务器、Web 更新信息等。
典型方法:
- `GetSystems`
- `GetSystemInfo`
- `GetSysMenus`
- `GetSystemLoginInfo`
- `GetProSysType`
- `GetDbServer`
- `GetWebUpdateInfo`
### 5.3 动态模块与单据
入口:`ModuleAjaxController`,路径为 `/Api/ModuleAjaxApi`
这是项目最核心的业务入口,围绕“模块配置驱动”的 ERP/MES 页面和单据能力展开。前端传入 `ModuleId``MenuId``method` 等参数后,后端从系统配置表和业务表中组装模块元数据、字段、列表、明细、审核、附件、右键菜单、桌面数据等。
核心实现:
- `ModuleImpl implements ModuleImplService`:模块初始化、字段数据、模块数据、单据保存、审核、附件、权限、桌面配置。
- `DataImpl`:动态 SQL、表结构、字段、主键、存储过程、附件权限、模块配置数据读取。
- `ModuleEventImpl`:模块数据加载、保存、状态变化、附件上传等事件扩展点。
- `MapImpl`:区域和地图相关接口实现。
典型方法:
- `GetModuleIniParams`
- `GetModuleData`
- `GetFieldData`
- `GetBillIniParams`
- `AddOrUpd`
- `Delete`
- `SaveBill`
- `GetModuleCfg`
- `GetModuleDetailsData`
- `GetAuditHistory`
- `GetRoles` / `SaveRoles`
- `GetBSDesktopData`
### 5.4 文件与附件
入口:`FileUploadController`,路径为 `/Api/FileUploadApi`
核心实现:
- `FileImpl`:文件保存、校验、附件基础记录。
- `FileUtil` / `PathUtil` / `ZipUtil`:路径处理、实际文件保存/删除、批量压缩。
- `ModuleImpl` / `DataImpl`:附件权限检查、附件记录入库、模块关联。
- `OfficeUtil` / `CreateWordUtil`:文档处理、预览或转换相关能力。
典型方法:
- `DoWebUpload`
- `DownLoadFiels`
- `DoDelete`
- `SaveViewModule`
## 6. 数据访问架构
项目同时使用 MyBatis Mapper XML 和 Spring `JdbcTemplate`
```mermaid
flowchart LR
Business["业务实现<br/>ModuleImpl / DataImpl / SysUserImpl / SystemImpl"]
Factory["AllInOneSqlFactory"]
Type["custom.database.type<br/>dm / kingbase"]
DmProvider["DmAllInOneSqlProvider"]
KbProvider["KingbaseAllInOneSqlProvider"]
DmMapper["DMCrmMapper<br/>DMCrmMapper.xml"]
CrMapper["CRMapper<br/>CustomerMapper.xml"]
PageMapper["PageBreaksMapper<br/>PageBreaks.xml"]
Jdbc["JdbcTemplate / NamedParameterJdbcTemplate"]
DB[("数据库")]
Business --> Factory
Type --> Factory
Factory --> DmProvider
Factory --> KbProvider
DmProvider --> DmMapper
KbProvider --> CrMapper
Business --> PageMapper
Business --> Jdbc
DmMapper --> DB
CrMapper --> DB
PageMapper --> DB
Jdbc --> DB
```
数据访问特点:
- `application.properties` 通过 `custom.database.type` 指定当前数据库类型,当前配置为 `dm`
- `AllInOneSqlFactory#createProvider()` 根据数据库类型创建 `DmAllInOneSqlProvider``KingbaseAllInOneSqlProvider`
- 达梦数据库主要走 `DMCrmMapper``DMCrmMapper.xml`
- 人大金仓或通用查询主要走 `CRMapper``CustomerMapper.xml`
- 大量复杂业务仍直接使用 `JdbcTemplate``NamedParameterJdbcTemplate` 拼装动态 SQL。
- `mybatis-config.xml` 配置了 PageHelper 插件,方言为 `dm`
## 7. 配置与运行边界
主要配置文件:`WebErp/weberp/src/main/resources/application.properties`
关键配置项:
- `server.port=8088`:服务端口。
- `custom.database.type=dm`:当前 SQL 方言/Provider 选择。
- `spring.datasource.*`:数据库连接、驱动和 Hikari 连接池配置。
- `mybatis.mapper-locations=classpath:mapper/*.xml`Mapper XML 位置。
- `pagehelper.helper-dialect=dm`:分页方言。
- `spring.data.redis.*`Redis 连接配置。
- `language=Language_CN`:语言包选择。
- `jwt.expiration``SingleUser``RestInitPwd``LockErrPwd` 等:登录和安全相关开关。
安全边界:
- `SecurityConfig` 当前只放行指定 `/Api/*` 入口,其余请求默认拒绝。
- `CorsConfig` 明确列出允许的前端来源,并允许携带凭证。
- Controller 入口放行后,业务级登录校验主要由 `BaseHandler``@RequestCheck` 决定。
注意:配置文件中包含数据库、Redis 等环境信息,生产环境建议通过环境变量、外部配置中心或部署平台密钥管理注入,避免将敏感连接信息写入源码仓库。
## 8. 模块配置驱动模型
从代码结构看,系统大量业务并非通过固定 Java DTO 和固定 SQL 完成,而是依赖数据库中的模块配置表、字段配置、控件配置、菜单配置和权限配置动态组装页面与数据。
```mermaid
flowchart TB
Front["前端请求<br/>ModuleId / MenuId / method"]
Init["GetModuleIniParams"]
ConfigTables["模块配置表<br/>字段 / 控件 / 菜单 / 权限 / 审核"]
EntityBuild["Entity.System / Entity.Control<br/>组装模块模型"]
DataQuery["DataImpl / ModuleImpl<br/>动态查询业务数据"]
Response["BaseResponse<br/>模块结构 + 数据 + 权限"]
Front --> Init
Init --> ConfigTables
ConfigTables --> EntityBuild
EntityBuild --> DataQuery
DataQuery --> Response
Response --> Front
```
这种架构的影响:
- 新增业务模块时,可能更多依赖数据库配置和元数据,而不是新增独立 Controller。
- `ModuleId` 是贯穿模块初始化、数据查询、附件、审核、权限的核心参数。
- `Entity.Control` 下的 `Field``GridPanel``TreePanel``ComboBox` 等对象承担前端控件描述能力。
- `BaseModule``BillModule``ModuleBaseEntity` 等模型承载基础模块和单据模块配置。
## 9. 扩展点
常见扩展方式:
1. 新增 Ajax 方法:在对应 Controller 中新增 public 无参方法,通过前端 `method``action` 调用,并按需添加 `@RequestCheck`
2. 新增模块能力:优先检查是否能通过模块配置表、字段配置、菜单配置实现,再考虑修改 `ModuleImpl``DataImpl`
3. 新增数据库方言:实现 `AllInOneSqlProvider`,并在 `AllInOneSqlFactory` 中按新的 `custom.database.type` 分支返回 Provider。
4. 新增 Mapper 查询:在 Mapper 接口中定义方法,并在 `resources/mapper/*.xml` 中补充对应 SQL。
5. 新增文件处理能力:扩展 `FileUploadController``FileImpl``FileUtil``Office` 工具类。
6. 新增业务事件:通过 `ModuleEventImpl` 的加载、保存、状态变化、附件上传等事件机制接入。
## 10. 维护建议
- 优先理解 `BaseHandler -> OptBaseHandler -> OptBaseImpl/BaseImpl` 这条公共链路,再看具体业务方法。
- 排查接口问题时,先确认请求路径、`method/action``ModuleId/MenuId``@RequestCheck` 参数校验和登录状态。
- 修改数据访问逻辑时,先确认当前数据库类型和实际使用的是 Mapper XML、SQL Provider 还是 JdbcTemplate 动态 SQL。
- 对涉及附件、审核、权限、单据保存的改动,应同步验证 `ModuleImpl``DataImpl` 和数据库配置表的联动。
- 生产配置建议外置,尤其是数据库地址、用户名、密码、Redis 地址、JWT 相关配置。
Binary file not shown.
+63
View File
@@ -0,0 +1,63 @@
# LSERP
###
LSERP/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ ├── project/ # 项目核心代码包
│ │ │ │ ├── controller/ # 控制器层
│ │ │ │ ├── service/ # 服务层
│ │ │ │ │ ├── service/ # 服务接口
│ │ │ │ │ └── impl/ # 服务实现
│ │ │ │ ├── mapper/ # DAO接口
│ │ │ │ ├── entity/ # 实体类
│ │ │ │ ├── converter/ # 数据转换层
│ │ │ │ ├── dto/ # 数据传输对象
│ │ │ │ │ └── Module/ # 自定义返回类(匹配out或自定义返回类)
│ │ │ │ └── utils/ # 工具类(项目内工具)
│ │ │ └── utils/ # 与project同级的工具包
│ │ │ ├── PermissionUtil/ # 数据类型转换工具
│ │ │ ├── FormParamUtil/ # 表单获取工具
│ │ │ ├── SystemMenuUtil/ # DLL文件转换工具
│ │ │ └── PublicUtil/ # 数据类型转换工具
│ │ └── resources/
│ │ ├── mapper/ # MyBatis XML映射文件
│ │ └──application.properties # Spring Boot配置
│ └── test/
│ └── java/ # 单元测试
└── pom.xml # Maven配置文件
结构更改
LSERP/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── example/
│ │ │ ├── project/ # 项目核心代码包
│ │ │ │ ├── controller/ # 控制器层
│ │ │ │ ├── service/ # 服务层
│ │ │ │ │ ├── service/ # 服务接口
│ │ │ │ │ └── impl/ # 服务实现
│ │ │ │ ├── mapper/ # DAO接口
│ │ │ │ ├── entity/ # 实体类
│ │ │ │ ├── converter/ # 数据转换层
│ │ │ │ ├── dto/ # 数据传输对象
│ │ │ │ │ └── Module/ # 自定义返回类(匹配out或自定义返回类)
│ │ │ │ └── utils/ # 工具类(项目内工具)
│ │ │ ├── utils/ # 与project同级的工具包
│ │ │ └── Entity/ # 实体类(修改后,sql直接用List<Map>接受,不再写实体类)
│ │ │ ├── PermissionUtil/ # 数据类型转换工具
│ │ │ ├── FormParamUtil/ # 表单获取工具
│ │ │ ├── SystemMenuUtil/ # DLL文件转换工具
│ │ │ └── PublicUtil/ # 数据类型转换工具
│ │ └── resources/
│ │ ├── mapper/ # MyBatis XML映射文件
│ │ └──application.properties # Spring Boot配置
│ └── test/
│ └── java/ # 单元测试
└── pom.xml # Maven配置文件
+37
View File
@@ -0,0 +1,37 @@
# LSERP
#### 介绍
1111
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
+38
View File
@@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
+36
View File
@@ -0,0 +1,36 @@
# LSERP-MES
#### Description
111
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
+37
View File
@@ -0,0 +1,37 @@
# LSERP-MES
#### 介绍
111
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
File diff suppressed because one or more lines are too long
@@ -0,0 +1,123 @@
# WebErp 安全漏洞自查工作自证材料
报告日期:2026-06-25
报告类型:企业安全漏洞定期自查与风险规避自证材料
适用范围:WebErp / weberp Spring Boot 后端项目
报告口径:对外自证,展示已开展的安全自查、已建设的风险规避措施、风险识别记录与后续处置安排。
## 1. 项目概况与扫描范围
本次自查对象为 WebErp 后端工程,核心模块为 `WebErp/weberp`。项目采用 Spring Boot、Maven、多数据库驱动、MyBatis、文件处理、Office 文档转换、远程资源下载、JWT 登录态、GraalJS 表达式执行等能力。
本次自查覆盖以下范围:
| 类别 | 覆盖内容 | 证据来源 |
| --- | --- | --- |
| 依赖与构建 | Maven 父子 POM、依赖树、关键第三方组件版本 | `WebErp/pom.xml``WebErp/weberp/pom.xml``weberp/target/dependency-tree.txt` |
| 配置安全 | 数据库连接、运行配置、跨域配置、脚本执行开关 | `application.properties``CorsConfig.java``JsEngine.java` |
| 认证授权 | Spring Security 入口放行、业务层登录校验、公开接口白名单 | `SecurityConfig.java``BaseHandler.java``PublicApiRegistry.java` |
| SQL 安全 | MyBatis 动态 SQL、SQL 片段校验、字段名白名单 | `mapper/*.xml``SqlSafetyGuard.java`、SQL Provider 实现 |
| 文件与下载 | 文件路径校验、压缩包解压、远程下载、在线预览 | `FileUtil.java``ZipUtil.java``RemoteDownloadGuard.java``ToolsHandler.java` |
| 脚本与命令 | GraalJS 沙箱配置、系统命令执行点复核 | `JsEngine.java``OfficeUtil.java``FormatFactoryUtil.java` |
| 自动化证据 | 安全回归测试、依赖树生成、工具可用性确认 | `SecurityRegressionTest.java`、Maven 命令执行记录 |
说明:本报告为安全漏洞自查工作留档材料,不等同于第三方渗透测试报告或等保测评报告。
## 2. 自查方法与证据来源
本次自查采用静态代码扫描、配置审阅、依赖版本核验、关键安全控制点测试和公开漏洞库查询相结合的方式。
已执行并形成证据的检查项:
| 检查项 | 方法 | 结果 |
| --- | --- | --- |
| 安全回归测试 | 执行 `mvn -q -Dtest=SecurityRegressionTest test` | 通过,覆盖路径越权、Zip Slip、CORS、远程下载限制、SQL 片段校验、公开接口白名单等场景 |
| Maven 依赖树 | 执行 Maven dependency tree 并输出到 `weberp/target/dependency-tree.txt` | 已生成,可用于依赖版本留档 |
| OSV 漏洞查询 | 对关键 Maven 组件进行 OSV API 查询 | 发现 Jackson databind 仍有一项新披露风险需跟踪 |
| 工具环境确认 | 检查本机 `osv-scanner``dependency-check` 命令 | 当前环境未安装,已列入后续工具化改进 |
| 敏感配置审阅 | 扫描配置文件与安全相关关键字 | 发现数据库连接配置仍需脱敏入库治理,报告正文已脱敏展示 |
## 3. 风险识别记录台账
| 编号 | 风险名称 | 位置 | 等级 | 影响 | 现状证据 | 已有控制 | 处置方案 | 优先级 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| R-001 | 第三方依赖漏洞风险 | `com.fasterxml.jackson.core:jackson-databind:2.18.8` | 高 | 特定反序列化忽略属性绕过场景下,可能影响对象字段保护策略 | OSV 查询命中 `GHSA-5jmj-h7xm-6q6v`OSV 标注修复版本为 `2.18.9`,但当前 Maven Central 未查询到该版本,本地 Maven 解析也失败 | Jackson 已从旧版本升级到当前可打包版本;父 POM 已统一版本管理,避免父子 POM 版本漂移 | 持续跟踪可用修复版本;若 `2.18.9` 可解析则优先小版本升级;若不可用,则评估升级到后续可用安全版本并补跑兼容测试 | P0 |
| R-002 | 配置文件中存在真实数据库连接信息 | `weberp/src/main/resources/application.properties` 第 12 行附近 | 高 | 若配置文件被外发或提交到共享仓库,可能导致数据库访问凭证泄露 | 配置文件中仍有真实数据库连接串;本报告仅记录脱敏形态:`jdbc:dm://***:****/****?凭证=***` | 已约定生产真实配置应放在部署服务器本地;报告中不展示真实地址、账号或密码 | 立即轮换已暴露凭证;将仓库配置改为示例值;补充 `.gitignore` 排除本地与生产真实配置文件;对历史提交和制品进行泄露排查 | P0 |
| R-003 | 动态接口入口开放面较大 | `SecurityConfig.java``BaseHandler.java``PublicApiRegistry.java` | 中 | 若业务层校验缺失,可能导致未授权访问 | Spring Security 对动态 `/Api/**` 分发入口放行;业务层通过 `@RequestCheck` 和公开接口白名单进行控制 | `BaseHandler` 已引入 `PublicApiRegistry`,未列入白名单的 `CheckLogin=false` 方法会回落为需要登录;未匹配请求默认拒绝 | 持续审计所有 `CheckLogin=false` 方法;新增公开接口必须进入白名单并经过安全复核;对模块数据、文件预览、下载接口默认保持登录态要求 | P0 |
| R-004 | MyBatis 动态 SQL 拼接风险 | `mapper/*.xml``${...}` 片段及 SQL Provider | 高 | 若外部输入直接进入 SQL 片段,可能造成 SQL 注入或越权查询 | Mapper 文件中仍存在字段名、条件片段和完整 SQL 拼接点 | 已新增 `SqlSafetyGuard`;部分入口已对字段名、只读查询和条件片段进行白名单或危险关键字拦截 | 对所有 `${...}` 来源建立清单;字段名改为服务端白名单;条件片段逐步参数化;无法立即改造的入口必须先接入 `SqlSafetyGuard` | P0 |
| R-005 | 远程 URL 下载与服务端请求风险 | `FileUtil.java``ToolsHandler.java``WebUtil.java``CreateWordUtil.java``DateTimeUtil.java` | 高 | 若允许用户控制 URL,可能触发 SSRF、内网探测或下载超限 | `RemoteDownloadGuard` 已接入部分下载流程;仍存在多个 URL 请求入口需要继续统一治理 | `RemoteDownloadGuard` 限制协议、私有地址、链路本地地址、组播地址、重定向跳数和下载大小;配置项默认禁止私有地址 | 将残留 URL 请求入口统一接入远程下载守卫;重定向每跳复核;对在线预览类接口补充域名白名单或登录态要求 | P0 |
| R-006 | 文件路径穿越与压缩包解压风险 | `FileUtil.java``ZipUtil.java` | 中 | 文件读写或解压过程若未限制根目录,可能覆盖非授权路径 | 已有路径规范化、根目录匹配和压缩条目路径校验;回归测试覆盖路径越权和 Zip Slip | `ZipUtil` 对解压目标路径进行标准化并校验必须位于目标目录内;`FileUtil` 对文件虚拟路径和物理路径做规范化处理 | 持续保留回归测试;新增文件读写入口必须复用路径校验;压缩包处理增加大小和条目数量限制作为后续优化 | P1 |
| R-007 | GraalJS 脚本全访问风险 | `JsEngine.java``application.properties` | 中 | 若脚本全访问开启,表达式可能访问宿主环境能力 | `app.js.allow-all-access=false` 已配置;代码中仅在显式开启时允许全访问并输出告警 | 默认关闭 GraalJS 全访问;表达式执行使用独立上下文和缓存容量限制 | 保持默认关闭;若业务确需开启,必须形成变更审批、日志告警和最小权限说明;补充脚本危险语句测试 | P1 |
| R-008 | 系统命令执行点需持续复核 | `OfficeUtil.java``FormatFactoryUtil.java` | 中 | 若命令路径或参数可被外部输入污染,可能造成命令执行风险 | 代码中存在系统命令调用点,主要用于文件权限和格式转换 | 已将该类入口列为重点复核项;目前未在本报告中确认存在可利用外部输入链 | 对可执行文件路径、参数来源和工作目录进行白名单校验;禁止拼接 shell 字符串;记录命令执行审计日志 | P1 |
| R-009 | CORS 白名单与响应头暴露需环境化治理 | `CorsConfig.java` | 中 | 若跨域源配置过宽,可能扩大凭证跨域风险 | CORS 已采用白名单并允许携带凭证;测试覆盖不暴露全部响应头和拒绝异常方法 | 未使用通配源;限制请求方法;仅暴露必要响应头 | 将不同环境的允许源迁移到配置项;生产环境定期审计白名单;下线临时调试源 | P1 |
| R-010 | 安全扫描工具链不完整 | 本机工具环境 | 低 | 无法在本机直接运行标准化 OSV Scanner 或 OWASP Dependency-Check | 当前命令行未安装 `osv-scanner``dependency-check` | 已通过 OSV API 和 Maven 依赖树进行替代性核验 | 在 CI 或发布机补齐依赖漏洞扫描工具;形成扫描报告归档;对高危漏洞建立阻断规则 | P2 |
| R-011 | SQL 控制台日志与敏感信息日志风险 | `application.properties`、SQL 调试配置 | 中 | 开启 SQL 输出时,可能在日志中暴露业务字段、查询条件或敏感参数 | 配置中存在 MyBatis 控制台日志相关项,当前仍需按环境复核 | 部分日志级别已关闭;安全回归测试覆盖部分响应头与令牌场景 | 生产环境关闭 SQL 明文输出;日志脱敏账号、手机号、凭证和令牌;建立日志留存与访问控制 | P1 |
## 4. 已有安全控制与风险规避措施
| 控制领域 | 已有措施 | 自证说明 |
| --- | --- | --- |
| 依赖治理 | Maven 父 POM 统一管理关键组件版本;子模块保留真实业务依赖 | 降低父子 POM 版本漂移和重复依赖风险,便于后续集中升级 |
| 默认拒绝 | Spring Security 未匹配请求使用默认拒绝策略 | 减少非预期接口暴露 |
| 公开接口收敛 | `PublicApiRegistry` 集中维护公开方法 | 登录、验证码、基础系统信息等接口可公开;模块业务数据类接口默认需登录 |
| 登录态校验 | `BaseHandler` 基于 `@RequestCheck` 统一执行登录和参数校验 | 对动态分发 API 提供统一拦截层 |
| SQL 防护 | `SqlSafetyGuard` 提供字段名、只读查询和条件片段校验 | 对高风险动态 SQL 入口先建立拦截,再逐步参数化 |
| SSRF 防护 | `RemoteDownloadGuard` 限制协议、地址类型、重定向和下载大小 | 对远程下载流程建立边界控制 |
| 文件路径防护 | 文件路径规范化、根目录校验、压缩包条目路径校验 | 防止路径穿越和 Zip Slip |
| CORS 控制 | 采用具体源白名单,未使用任意源通配 | 携带凭证场景下减少跨域滥用风险 |
| JS 沙箱 | GraalJS 全访问默认关闭 | 降低表达式执行访问宿主能力的风险 |
| 回归测试 | `SecurityRegressionTest` 覆盖多项安全控制 | 形成可重复验证证据 |
## 5. 风险处置方案与整改优先级
| 优先级 | 处置事项 | 目标完成标准 |
| --- | --- | --- |
| P0 | 轮换并移除已提交配置中的真实数据库凭证 | 仓库配置仅保留示例值;真实配置仅存在于部署服务器本地;历史暴露凭证完成轮换 |
| P0 | 跟踪 Jackson databind 修复版本 | 修复版本可解析后完成升级、打包和安全回归测试;若采用后续可用安全版本,完成兼容验证 |
| P0 | 动态 SQL 治理 | 所有 `${...}` 来源登记;外部输入不得直接进入 SQL 片段;关键路径完成白名单或参数化 |
| P0 | 远程 URL 请求统一防护 | 所有用户可控 URL 请求入口接入 `RemoteDownloadGuard` 或域名白名单;重定向每跳校验 |
| P0 | 公开接口白名单治理 | `CheckLogin=false` 方法均有业务必要性说明;未列入公开白名单的接口必须要求登录 |
| P1 | CORS 与日志生产化治理 | CORS 源按环境配置;生产关闭 SQL 明文输出;日志中敏感字段完成脱敏 |
| P1 | 命令执行点复核 | 可执行文件路径与参数来源白名单化;禁止 shell 字符串拼接;补充审计日志 |
| P2 | 安全扫描工具链补齐 | CI 或发布流程中加入 OSV Scanner 或 OWASP Dependency-Check,并归档扫描结果 |
## 6. 定期漏洞自查机制
建议建立以下周期化机制,并将结果作为企业安全漏洞自查自证材料留档:
| 周期 | 自查动作 | 输出材料 |
| --- | --- | --- |
| 每月 | 依赖漏洞扫描、Maven 依赖树归档、关键漏洞公告复核 | 依赖漏洞扫描记录、风险处置台账 |
| 每季度 | 代码安全自查,重点检查鉴权、SQL、文件、远程请求、脚本执行、日志脱敏 | 季度安全自查报告、整改跟踪表 |
| 每次发版前 | 执行安全回归测试、检查配置是否含真实凭证、复核新增公开接口 | 发版安全检查清单、测试结果截图或日志 |
| 重大漏洞公告后 | 针对影响组件进行应急排查、临时规避、升级验证 | 应急响应记录、修复验证记录 |
| 配置变更时 | 复核数据库、Redis、短信、推送、跨域源等配置 | 配置变更审批与脱敏检查记录 |
建议固定归档材料:
- Maven 依赖树与关键依赖版本清单。
- OSV Scanner 或 OWASP Dependency-Check 报告。
- 安全回归测试结果。
- 风险识别记录与处置状态表。
- 配置脱敏检查记录。
- 公开接口白名单审计记录。
## 7. 附件证据清单
| 证据项 | 文件或命令 | 说明 |
| --- | --- | --- |
| 安全回归测试 | `mvn -q -Dtest=SecurityRegressionTest test` | 已通过,覆盖路径、压缩包、CORS、远程下载、SQL 与公开接口控制 |
| 依赖树 | `weberp/target/dependency-tree.txt` | 已生成,用于记录当前第三方组件版本 |
| 依赖漏洞来源 | [OSV GHSA-5jmj-h7xm-6q6v](https://osv.dev/vulnerability/GHSA-5jmj-h7xm-6q6v) | Jackson databind 新披露风险来源 |
| 鉴权控制 | `SecurityConfig.java``BaseHandler.java``PublicApiRegistry.java` | 入口放行、业务层校验与公开接口白名单 |
| SQL 控制 | `SqlSafetyGuard.java``mapper/*.xml` | 动态 SQL 风险识别与部分防护落点 |
| 下载控制 | `RemoteDownloadGuard.java``FileUtil.java` | 远程下载协议、地址、重定向和大小控制 |
| 文件控制 | `FileUtil.java``ZipUtil.java` | 路径规范化、根目录校验和 Zip Slip 防护 |
| 脚本控制 | `JsEngine.java``application.properties` | GraalJS 全访问默认关闭 |
| 工具环境限制 | `osv-scanner --version``dependency-check --version` | 当前本机未安装,建议在 CI 或发布机补齐 |
## 8. 结论
本项目已开展面向依赖、配置、认证授权、SQL、文件处理、远程下载、脚本执行、跨域和回归测试的安全漏洞自查工作,并已具备多项风险规避措施。当前风险主要集中在配置凭证治理、Jackson 新披露漏洞跟踪、动态 SQL 全量收敛、残留远程 URL 请求统一防护和生产环境安全配置固化。
上述事项已纳入整改跟踪台账。后续通过定期扫描、发版前安全检查、重大漏洞应急复核和自动化安全回归测试,持续证明企业具备安全漏洞风险识别、处置和规避能力。
+299
View File
@@ -0,0 +1,299 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>WebErp</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WebErp</name>
<url>http://maven.apache.org</url>
<modules>
<module>weberp</module>
</modules>
<repositories>
<repository>
<id>AsposeRepository</id>
<name>Aspose Official Repository</name>
<url>https://releases.aspose.com/java/repo/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>com.e-iceblue</id>
<name>Spire Repository</name>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>3.4.3</spring-boot.version>
<jackson.version>2.18.8</jackson.version>
<logback.version>1.5.18</logback.version>
<mysql.version>8.3.0</mysql.version>
<mssql-jdbc.version>12.8.2.jre11</mssql-jdbc.version>
<mybatis.version>3.5.17</mybatis.version>
<mybatis-spring-boot.version>3.0.4</mybatis-spring-boot.version>
<jjwt.version>0.11.5</jjwt.version>
<gson.version>2.10.1</gson.version>
<graaljs.version>24.1.1</graaljs.version>
<jaxb.version>2.3.1</jaxb.version>
<juniversalchardet.version>1.0.3</juniversalchardet.version>
<jai-imageio.version>1.4.0</jai-imageio.version>
<itext7.version>7.2.5</itext7.version>
<spire-doc.version>13.5.3</spire-doc.version>
<spire-xls.version>14.8.2</spire-xls.version>
<spire-presentation.version>10.10.2</spire-presentation.version>
<aspose.version>23.6</aspose.version>
<zxing.version>3.5.1</zxing.version>
<javacv.version>1.5.10</javacv.version>
<commons-compress.version>1.26.0</commons-compress.version>
<zip4j.version>2.11.5</zip4j.version>
<hikaricp.version>4.0.3</hikaricp.version>
<dm-jdbc.version>8.1.4.181</dm-jdbc.version>
<pagehelper.version>1.4.7</pagehelper.version>
<jakarta-servlet.version>6.0.0</jakarta-servlet.version>
<junit.version>3.8.1</junit.version>
<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>${mssql-jdbc.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>${jakarta-servlet.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
<version>${graaljs.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
<version>${graaljs.version}</version>
</dependency>
<dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
<version>${graaljs.version}</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>com.googlecode.juniversalchardet</groupId>
<artifactId>juniversalchardet</artifactId>
<version>${juniversalchardet.version}</version>
</dependency>
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-core</artifactId>
<version>${jai-imageio.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>${itext7.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc</artifactId>
<version>${spire-doc.version}</version>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.xls</artifactId>
<version>${spire-xls.version}</version>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.presentation</artifactId>
<version>${spire-presentation.version}</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>${aspose.version}</version>
<classifier>jdk17</classifier>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-cells</artifactId>
<version>${aspose.version}</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-slides</artifactId>
<version>${aspose.version}</version>
<classifier>jdk16</classifier>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>${zxing.version}</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>${zxing.version}</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>${javacv.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>${commons-compress.version}</version>
</dependency>
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>${zip4j.version}</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>${hikaricp.version}</version>
</dependency>
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver8</artifactId>
<version>${dm-jdbc.version}</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
+244
View File
@@ -0,0 +1,244 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>WebErp</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>weberp</artifactId>
<packaging>jar</packaging>
<name>weberp</name>
<description>Spring Boot application module</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver8</artifactId>
</dependency>
<!-- Kingbase driver is intentionally disabled until the internal artifact is available. -->
<!--
<dependency>
<groupId>com.kingbase8</groupId>
<artifactId>kingbase8</artifactId>
<version>9.0.0</version>
</dependency>
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.googlecode.juniversalchardet</groupId>
<artifactId>juniversalchardet</artifactId>
</dependency>
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-core</artifactId>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<type>pom</type>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc</artifactId>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.xls</artifactId>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.presentation</artifactId>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<classifier>jdk17</classifier>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-cells</artifactId>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-slides</artifactId>
<classifier>jdk16</classifier>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
</dependency>
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>org.example.WebErpApplication</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>16</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

@@ -0,0 +1,718 @@
package org.example.Api;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.*;
import jakarta.servlet.http.*;
import org.example.Utils.LanguageUtil;
import org.example.Entity.BaseResponse.BaseResponse;
import org.example.Entity.CusException.CusException;
import org.example.Entity.System.LoginUserInfo;
import org.example.Entity.Attributes.*;
import org.example.Impl.BaseImpl;
import org.example.Utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.support.RequestContext;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.util.*;
import java.util.zip.GZIPOutputStream;
import org.example.Enums.LoginCode;
import static org.example.Utils.NativeExtensionUtils.*;
/**
* ==============================================================================
* 功能描述:BaseHandler 对外开放的接口父类
* ==============================================================================
*/
public abstract class BaseHandler {
private static final Logger log = LoggerFactory.getLogger(BaseHandler.class);
protected HttpServletRequest Request;
protected HttpServletResponse Response;
protected HttpSession Session;
protected Cookie Cookie;
protected ServletContext Application;
protected HttpServletRequest context;
protected String methodName, ModuleId, MenuId, MenuCode, language;
protected BaseResponse response;
protected int currPage = 0, pageSize = 0, startsize = 0;
protected boolean isCustomer = false, isWindowsDirver = true; // IsCustomer:标识为游客客户端 IsWindowsDirver:PC端访问
protected LocalDateTime startTime, endTime;
private static long requestCount = 0, maxPMins = 0, lastCount = 0, lastMins = 0;
private static LocalDateTime startDate = LocalDateTime.now();
private static LocalDateTime maxPDate = LocalDateTime.now();
public RequestContext requestContext;
@Autowired
private ObjectMapper objectMapper;
protected String getUserName() {
return getUser() != null ? getUser().UserName : "";
}
protected String getUserId() {
return getUser() != null ? getUser().UserId : "";
}
protected LoginUserInfo _user;
protected LoginUserInfo getUser() {
return _user = getBImpl().getUser();
}
protected String getUserSessionName() {
return getBImpl().getUserSessionName();
}
protected String getSessionId() {
return getBImpl().getSessionId();
}
protected String getDriver() {
return getBImpl().getDriver();
}
protected String getAppDomain() throws UnsupportedEncodingException {
return getBImpl().getAppDomain();
}
/**
* 附件路径
*/
protected String getAttcPath() {
return getBImpl().getAttcPath();
}
//【200426】未找到的提示
protected String notFindModuleMsg;
protected DbOperator getDbOperator() {
return getDbOprator();
}
protected DbOperator getDbOprator() {
return getBImpl().getDbOperator();
}
private BaseImpl _bImpl = null;
protected BaseImpl getBImpl() {
if (_bImpl == null) {
_bImpl = new BaseImpl();
}
return _bImpl;
}
public void processRequest(HttpServletRequest ctx) throws IOException, ServletException {
boolean isDebug = toBoolean(WebConfigUtil_web.get("debug", ""));
if (!isDebug) {
// 对应C#的DEBUG编译符号判断,可根据实际环境调整
isDebug = false;
}
_bImpl = null;
startTime = LocalDateTime.now();
// 网站访问量统计
requestCount++;
int mins = (int) Duration.between(startDate, LocalDateTime.now()).toMinutes();
if (mins > lastMins) {
lastMins = mins;
if (requestCount - lastCount > maxPMins) {
maxPDate = LocalDateTime.now();
maxPMins = requestCount - lastCount;
}
lastCount = requestCount;
}
SingleUserHandler.cacheKey = (getUserSessionName());
context = ctx;
Session = ctx.getSession();
Application = ctx.getServletContext();
initSystemParams(ctx);
response = new BaseResponse();
response.setSuccess(false);
response.setMsg("");
methodName = getMethod();
Class<?> type = this.getClass();
if (isNullOrEmpty(methodName)) {
response.setSuccess(false);
response.setMsg(LanguageUtil.WrongInterfaceName);
writeResponse();
return;
}
Method method = null;
try {
// out.println(method + " me");
method = type.getMethod(methodName);
} catch (NoSuchMethodException e) {
log.warn(String.valueOf(e.getMessage() + "Err:ApiFunctionName,Please CheckOut!!"));
response.setSuccess(false);
response.setMsg(LanguageUtil.WrongInterfaceName);
writeResponse();
return;
}
String mName = methodName.substring(0, 1) +
methodName.substring(methodName.length() - 2, methodName.length() - 1) +
"_" + methodName.length();
mName = mName.toUpperCase();
// out.println(mName + "mname");
try {
RequestCheckAttribute webCheck = AttributeUtils.getAttribute(method);
if (webCheck == null) {
webCheck = AttributeUtils.getCustomAttribute(type, RequestCheckAttribute.class);
}
if (webCheck != null) {
webCheck.setBImpl(getBImpl()); // 现在可以正常调用setter
}
log.debug(String.valueOf("当前方法:" + methodName + ",匹配的CheckParams" + (webCheck != null ? webCheck.CheckParams : "null") +
",匹配的Log" + (webCheck != null ? webCheck.Log : "null") +
",匹配的CheckLogin" + (webCheck != null ? webCheck.CheckLogin : "null")));
// out.println("webcheck是"+webCheck);
// 登录检查
boolean declaredPublic = webCheck != null && !webCheck.CheckLogin;
boolean allowedPublic = declaredPublic && PublicApiRegistry.isPublicEndpoint(type, methodName);
boolean requiresLogin = webCheck == null || webCheck.CheckLogin || (declaredPublic && !allowedPublic);
if (requiresLogin && !checkLoginByPro()) {
// if (true && !checkLoginByPro()) {
goLogin();
} else {
if (!isNullOrEmpty(getUserName())) {
ActiveUserUtil.active(
(getUser() != null && !isNullOrEmpty(getUser().Token) ?
getUser().Token.hashCode() + "" : getSessionId()),
getUserName()
);
}
String[] errMsg = new String[1];
if (webCheck == null || webCheck.validParams(errMsg)) {
getDbOperator().setCloseCon(true); // 使用同一个连接,提高速度
initReqPms();
// out.println(method + " 1me " + objectMapper.writeValueAsString(response) + " re ");
if (webCheck != null && webCheck.Cache && toBoolean(WebConfigUtil_web.get("Cache", ""))) {
Method finalMethod = method;
// out.println(method + " me1.5" + objectMapper.writeValueAsString(response) + "re");
String result = (String) webCheck.getCacheVal(this, () -> {
try {
finalMethod.invoke(this);
// out.println(finalMethod + " 2me" + objectMapper.writeValueAsString(response) + "re");
return objectMapper.writeValueAsString(response);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
response.setEncodedResult(result);
} else {
// out.println(method + " 3me" + objectMapper.writeValueAsString(response) + "re");
method.invoke(this);
}
log.debug(String.valueOf(response.getData() + "dataS"));
// getDbOperator().dispose();
endTime = LocalDateTime.now();
String logName = (webCheck == null) ? mName : (webCheck.Name != null ? webCheck.Name : mName);
double t = Duration.between(startTime, endTime).toMillis();
String idValue = getBImpl().Request("idValue");
StringBuilder msg = new StringBuilder();
if (isNullOrEmpty(idValue)) {
msg.append(String.format("执行%s,耗时%sms", logName, t));
if (!isNullOrEmpty(ModuleId)) {
msg.append(String.format(",模块:%s", ModuleId));
}
if (isDebug) {
msg.append(objectMapper.writeValueAsString(getBImpl().getAllRequest()));
}
} else {
msg.append(String.format("执行%s,耗时%sms,模块:%s,主键:%s", logName, t, ModuleId, idValue));
if (isDebug) {
msg.append(objectMapper.writeValueAsString(getBImpl().getAllRequest()));
}
}
if (webCheck == null || webCheck.Log) {
LoggerHandler.info(this, msg.toString());
}
if (t > 2000) {
LoggerHandler.dbLog(this, getDbOperator(), "warn", ModuleId, logName, JSON.Encode(getBImpl().getAllRequest()), t, "", null);
}
} else {
response.setSuccess(false);
response.setMsg(errMsg[0]);
}
if (webCheck == null || (webCheck.WriteRespose && response.isWriteResponse())) {
if (response.isSuccess() && isNullOrEmpty(response.getToken()) &&
!"LoginOut".equals(methodName) && getUser() != null && !isNullOrEmpty(getUser().Token)) {
response.setToken(JwtHelp.refreshToken(getUser(), getUser().Token, 7200));
if (!isNullOrEmpty(response.getToken())) {
getUser().Token = (response.getToken());
BaseImpl.setSessionVal(getUserSessionName(), getUser());
}
}
if (!isNullOrEmpty(response.getMsg()) &&
response.getMsg().contains("execute sql error")) {
response.setMsg(response.getMsg().substring(
response.getMsg().indexOf("execute sql error")));
}
writeResponse();
}
}
} catch (Exception ex) {
// System.err.println("捕获到异常类型:" + ex.getClass().getName());
// System.err.println("异常消息:" + ex.getCause().getMessage());
log.error("Exception caught", ex); // 打印完整堆栈,查看异常来源
String idValue = getBImpl().Request("idValue");
String errMsg = ExceptionSummaryUtil.summarizeForClient(ex);
boolean sqlExecuteError = ExceptionSummaryUtil.containsMessage(ex, "execute sql error");
log.debug(String.valueOf("Err:errMsg 方法里有异常错误,排查——>" + methodName));
String errStackMsg = "错误:" + errMsg;
StringBuilder msg = new StringBuilder();
if (isNullOrEmpty(idValue)) {
msg.append(String.format("接口:%s,%s", mName, errStackMsg));
} else {
msg.append(String.format("接口:%s,模块:%s,主键:%s,%s", mName, ModuleId, idValue, errStackMsg));
}
Response.reset();
response = new BaseResponse();
response.setSuccess(false);
response.setMsg(LanguageUtil.ServerError +
"<a href='" + getAppDomain() + "/logs/err.txt' style='color:blue;' target='_blank'>查看详情</a>" + msg);
if (isDebug) {
response.setMsg(errMsg);
}
if (!(ex instanceof CusException) || ((CusException) ex).Log) {
if (isDebug || !sqlExecuteError) {
LoggerHandler.error(msg, ex);
} else {
LoggerHandler.dbLog(this, getDbOperator(), "error", ModuleId, methodName,
JSON.Encode(getBImpl().getAllRequest()), 0, msg.toString().replace(mName, methodName), ex);
}
}
writeResponse();
} finally {
if (getBImpl() != null) {
getBImpl().getReqHandler().clearPms();
}
}
}
/**
* 验证完后,初始化参数
*/
protected void initReqPms() {
language = getBImpl().Request("lg", "cn");
currPage = parseInt(getBImpl().Request("currPage", getBImpl().Request("page", "1")));
pageSize = parseInt(getBImpl().Request("pageSize", getBImpl().Request("limit", "-1")));
isWindowsDirver = toBoolean(getBImpl().Request("windowsDirver", "1"));
ModuleId = getBImpl().Request("ModuleId").split(",")[0]; // PC端用
MenuId = parseInt(getBImpl().Request("MenuId", getBImpl().Request("menuid"))) + ""; // 通用
MenuCode = getBImpl().Request("menucode"); // 手机端用
ModuleId = isNullOrEmpty(ModuleId) ? MenuCode : ModuleId;
if (!isNullOrEmpty(ModuleId)) {
ModuleId = ModuleId.replace("\r", "").replace("\n", "");
}
MenuCode = ModuleId;
startsize = (currPage - 1) * pageSize;
startsize = Math.max(startsize, 0);
// 【200426】未找到的msg
notFindModuleMsg = "未找到模块号【" + ModuleId + "】的配置数据,请检查相应模块的配置是否正确!可能是多余的空格、回车,数字字母写错,模块暂未配置等情况!";
}
protected String getMethod() {
if (requestContext != null) {
// 从请求上下文中获取路由数据(模拟RouteValueDictionary
Map<String, Object> routeValues = getRouteValues(requestContext);
if (routeValues.containsKey("method")) {
Object methodValue = routeValues.get("method");
return methodValue != null ? methodValue.toString() : "";
} else {
return getBImpl().Request("method", getBImpl().Request("action"));
}
}
return getBImpl().Request("method", getBImpl().Request("action"));
}
// 辅助方法:获取路由参数(根据实际框架实现)
private Map<String, Object> getRouteValues(RequestContext requestContext) {
// 1. 若使用Spring MVC,可通过RequestContextHolder获取请求参数
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
// 2. 转换请求参数为Map(包含路由参数和请求参数)
return FormParamUtil.convertToMyBatisParamMap(request);
}
return new HashMap<>();
}
// public static void gZipEncodePage() {
// HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).Request();
// HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
//
// String acceptEncoding = request.getHeader("Accept-Encoding");
// if (!isNullOrEmpty(acceptEncoding) &&
// (acceptEncoding.contains("gzip") || acceptEncoding.contains("deflate"))) {
//
// if (acceptEncoding.contains("gzip")) {
//
// response.setHeader("Content-Encoding", "gzip");
// response.setOutputStream(new GZIPOutputStream(response.getOutputStream()));
//
// } else if (acceptEncoding.contains("deflate")) {
// // 实现deflate压缩
// }
// }
// }
private static String webVer = WebConfigUtil_web.get("WebVersion", "1.0.0.0");
/**
* 回写数据
*/
protected void writeResponse() throws IOException {
HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
resp.setHeader("WebAppVer", webVer);
if (resp.isCommitted()) {
log.debug(String.valueOf("响应已提交,跳过重复写入:" + Request.getRequestURI()));
return;
}
// String content = isNullOrEmpty(response.getEncodedResult()) ?
// objectMapper.writeValueAsString(response) : response.getEncodedResult();
String content = isNullOrEmpty(response.getEncodedResult()) ?
JSON.Encode(response) : response.getEncodedResult();
String recodings = Request.getHeader("Response-Encoding");
boolean gzipResponse = recodings != null && recodings.contains("gzip");
if (Request.getHeader("Referer") != null) {
String refDom = getDomainFromUrl(Request.getHeader("Referer"));
String curUrl = getDomainFromUrl(Request.getRequestURL().toString());
if (!refDom.equals(curUrl)) {
resp.setHeader("Access-Control-Allow-Origin", refDom);
resp.setHeader("Access-Control-Allow-Credentials", "true");
}
} else {
resp.setHeader("Access-Control-Allow-Origin", "*");
}
if (gzipResponse) {
content = URLEncoder.encode(content, StandardCharsets.UTF_8);
content = GZipUtil.gZip(content);
resp.setHeader("Response-Encoding", "gzip");
}
resp.setContentType("text/plain;charset=UTF-8");
if (!Response.isCommitted()) {
try (OutputStream os = resp.getOutputStream()) {
os.write(content.getBytes(StandardCharsets.UTF_8));
os.flush();
} catch (Exception e) {
// 捕获写入异常,避免因流关闭/已提交导致的崩溃
log.debug(String.valueOf("响应已提交,跳过重复写入:" + Request.getRequestURI()));
throw new IOException("写入响应流失败:" + e.getMessage(), e);
}
}
}
private String getDomainFromUrl(String url) {
try {
URL urlObj = new URL(url);
return urlObj.getProtocol() + "://" + urlObj.getAuthority();
} catch (Exception e) {
return "";
}
}
/**
* 初始化系统参数
*/
protected void initSystemParams(HttpServletRequest ctx) {
try {
ctx.setCharacterEncoding("UTF-8");
this.Request = ctx;
this.Response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
this.Response.setContentType("text/plain");
// 从 ctx 重新获取 Session,避免依赖 this.Session 字段
// HttpSession session = ctx.getSession(false); // 注意:false 表示不创建新 Session
// // 用户信息初始化
// _user = (LoginUserInfo) session.getAttribute(getUserSessionName());
// if (getUser() == null) {
// String userId = getBImpl().Request("userid");
// String userName = getBImpl().Request("username");
// if (!isNullOrEmpty(userId) && !isNullOrEmpty(userName)) {
// _user = new LoginUserInfo();
// getUser().UserId = (userId);
// getUser().UserName = (userName);
// session.setAttribute(getUserSessionName(), getUser());
// }
// }
} catch (Exception e) {
LoggerHandler.error("inierror", e);
}
}
/**
* 返回给客户端登录的指令
*/
protected void goLogin() throws IOException {
String authorization = context == null ? "" : context.getHeader("Authorization");
// 2. 统一将 null 转换为空字符串,避免后续调用方法时报错
authorization = (authorization == null) ? "" : authorization;
if (!isNullOrEmpty(authorization) && authorization.startsWith("Bearer ")) {
// log("登录失效:" + authorization);
}
response.setSuccess(false);
response.setMsg("response_login");
writeResponse();
}
/**
* 重定向到指定页面
*/
protected void redirect(String url, Object data) {
response.setSuccess(false);
response.setMsg("response_redirect");
Map<String, Object> redirectData = new HashMap<>();
redirectData.put("url", url);
redirectData.put("data", data);
response.setData(redirectData);
}
/**
* 向页面输送脚本
*/
protected void registerScript(String script, Object data) {
response.setSuccess(false);
response.setMsg("response_RegisterScript");
Map<String, Object> scriptData = new HashMap<>();
scriptData.put("script", script);
scriptData.put("data", data);
response.setData(scriptData);
}
/**
* 检查参数是否为空,被RequestCheck类替代
*/
protected boolean checkParam(String paramname, Object paramval) {
boolean ok = true;
if (paramval instanceof Integer) {
if ((Integer) paramval == 0) {
ok = false;
}
} else if (paramval == null || isNullOrEmpty(paramval.toString())) {
ok = false;
}
if (!ok) {
response.setSuccess(false);
response.setMsg(String.format("%s:%s", LanguageUtil.GetString("InvalidParameter"), paramname));
}
return ok;
}
/**
* 检查登录状态
*/
// @RequestCheck(CheckLogin = false)
public boolean checkLogin() {
return checkLoginByPro();
}
protected boolean checkLoginByPro() {
boolean isLoggedIn = getUser() != null && !"0".equals(getUser().UserId);
// out.println("isLoggedIn: " + isLoggedIn + getUser().UserName);
response.setSuccess(isLoggedIn);
response.setData(isLoggedIn ? getUser() : null);
response.setSharToken(toBoolean(WebConfigUtil_web.get("SharLogin", "1")));
if (ToInt32(WebConfigUtil.get("MsgBtnOrder", "0")) == 1) {
response.AppCfg = new HashMap<>();
response.AppCfg.put("MsgBtnOrder", 1);
}
if (isLoggedIn && "CheckLogin".equals(methodName)) {
if (SingleUserHandler.hasUnLoginUser(getSessionId()) ||
(!SingleUserHandler.hasSessionUser(getSessionId()) && SingleUserHandler.hasLoginUser(getUser().UserId))) {
loginOut();
response.setSuccess(false);
response.setData(null);
} else {
SingleUserHandler.add(getSessionId(), getUser().UserId);
}
if (response.isSuccess() && isDefaultPwd(getUser().Pwd) && toBoolean(WebConfigUtil_web.get("RestInitPwd", ""))) {
response.setMsg("请修改密码!");
response.setOther(LoginCode.ResetPwd);
}
if (isNullOrEmpty(getUser().Token) && !toBoolean(WebConfigUtil_web.get("SharLogin", "1"))) {
response.setToken(JwtHelp.createToken(getUser(), 7200));
}
}
// out.println("返回的正否" + response.isSuccess());
return response.isSuccess();
}
protected boolean isDefaultPwd(String pwd) {
return "51B4FCEDBC944C6F5627E732CD9560B8B1204FDB".equals(pwd) ||
"E0B97F132980BB0856ECC51BA256626F3CB68D11".equals(pwd) ||
"A839A93FD1A6699CAA208BB1DB9E2D25A7013E86".equals(pwd);
}
// @RequestCheckAttribute(log = false)
public void loginOut() {
int delay = parseInt(getBImpl().Request("delay"));
String userId = "", sessionId = getSessionId();
if (getUser() == null) {
return;
}
userId = getUser().UserId;
// out.println(userId + "userid:" + sessionId);
if (delay > 0) {
SingleUserHandler.waitLoginOut(sessionId);
DateTimeUtil.setTimeOut(() -> {
if (SingleUserHandler.hasWaitUnLoginUser(sessionId)) {
SingleUserHandler.unLogin(sessionId);
}
}, delay * 1000);
} else {
Session.removeAttribute(getUserSessionName());
SingleUserHandler.remove(sessionId);
JwtHelp.removeUserCache(getUser());
CacheUtil.remove(getUser().Token);
CacheUtil.clearUserCache(getUser().UserName, getUser().UserId);
if (getBImpl().isPhone()) {
response.setOther(0);
}
}
response.setData(null);
response.setSuccess(true);
}
public void unLoginOut() {
SingleUserHandler.unLogin(getSessionId());
response.setSuccess(true);
}
/**
* 清除服务器缓存
*/
// @RequestCheckAttribute(checkLogin = false)
public void clearCache() {
CacheUtil.clearCache();
response.setSuccess(true);
}
/**
* 获取活跃用户
*/
// @RequestCheckAttribute(checkLogin = true)
public void getActiveUser() {
Object[] users = ActiveUserUtil.getActiveUser();
response.setTot(users == null ? 0 : users.length);
response.setData(users);
response.setSuccess(true);
}
/**
* 获取平均请求数
*/
// @RequestCheckAttribute(checkLogin = true)
public void getAvgRequest() {
boolean reset = toBoolean(getBImpl().Request("reset"));
int mins = Math.max((int) Duration.between((Temporal) startDate, LocalDateTime.now()).toMinutes(), 1);
Date StartDate = Date.from(
startDate.atZone(ZoneId.systemDefault()) // 绑定系统默认时区
.toInstant() // 转换为 Instant
);
LocalDateTime now = LocalDateTime.now();
Date nowDate = Date.from(now.atZone(ZoneId.systemDefault()).toInstant());
Map<String, Object> data = new Hashtable<>();
data.put("tot", requestCount);
data.put("start", startDate);
data.put("avg", requestCount / Math.max(1, mins));
data.put("maxps", maxPMins);
data.put("maxPDate", maxPDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
data.put("mins", mins);
data.put("runed", DateTimeUtil.getDateDiff(StartDate, nowDate));
response.setData(data);
response.setSuccess(true);
if (reset) {
resetPCount();
}
}
// @RequestCheckAttribute(checkLogin = false)
public void getDate() {
response.setSuccess(true);
response.setData(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
private void resetPCount() {
startDate = LocalDateTime.now();
requestCount = 0;
maxPMins = 0;
lastMins = 0;
}
public boolean isReusable() {
return toBoolean(WebConfigUtil_web.get("ReusaHandler", "1"));
}
}
@@ -0,0 +1,289 @@
package org.example.Api;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.example.Entity.System.LoginUserInfo;
import org.example.Impl.BaseImpl;
import org.example.Utils.DateTimeUtil;
import org.example.Utils.DbOperator;
import org.example.Utils.NativeExtensionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 系统日志记录入口
*/
@Service
public class LoggerHandler {
@Autowired
private static JdbcTemplate jdbcTemplate;
private static final Log log = LogFactory.getLog(LoggerHandler.class);
private static final Lock lockObj = new ReentrantLock();
private static Date lastCheckDate = new Date();
public static void debug(Object happenobj, Object message) {
if (log.isDebugEnabled()) {
try {
log.debug(new LogInfo(happenobj).setMsg(message));
} catch (Exception e) {
error(message, e);
}
}
}
public static void debug(Object happenobj, Object message, Exception exception) {
if (log.isDebugEnabled()) {
try {
log.debug(new LogInfo(happenobj).setMsg(message).setException(exception));
} catch (Exception e) {
error(message, e);
}
}
}
public static void error(Object happenobj, Object message) {
if (log.isErrorEnabled()) {
try {
log.error(new LogInfo(happenobj).setMsg(message));
} catch (Exception e) {
error(message, e);
}
}
}
public static void error(Object happenobj, Object message, Exception exception) {
if (log.isErrorEnabled()) {
try {
log.error(new LogInfo(happenobj).setMsg(message).setException(exception));
} catch (Exception ignored) {
}
}
}
public static void fatal(Object happenobj, Object message) {
if (log.isFatalEnabled()) {
try {
log.fatal(new LogInfo(happenobj).setMsg(message));
} catch (Exception e) {
error(message, e);
}
}
}
public static void fatal(Object happenobj, Object message, Exception exception) {
if (log.isFatalEnabled()) {
try {
log.fatal(new LogInfo(happenobj).setMsg(message).setException(exception));
} catch (Exception e) {
error(message, e);
}
}
}
public static void info(Object happenobj, Object message) {
if (log.isInfoEnabled()) {
try {
log.info(new LogInfo(happenobj).setMsg(message));
} catch (Exception e) {
error(message, e);
}
}
}
public static void info(Object happenobj, Object message, Exception exception) {
if (log.isInfoEnabled()) {
try {
log.info(new LogInfo(happenobj).setMsg(message).setException(exception));
} catch (Exception e) {
error(message, e);
}
}
}
public static void warn(Object happenobj, Object message) {
if (log.isWarnEnabled()) {
try {
log.warn(new LogInfo(happenobj).setMsg(message));
} catch (Exception e) {
error(message, e);
}
}
}
public static void warn(Object happenobj, Object message, Exception exception) {
if (log.isWarnEnabled()) {
try {
log.warn(new LogInfo(happenobj).setMsg(message).setException(exception));
} catch (Exception e) {
error(message, e);
}
}
}
public static void dbLog(Object happenobj, DbOperator dbOperator, String level, String dllcoid,
String method, String args, double passT, String msg, Exception exception) {
// String conStr = dbOperator.ConnectionString;
// if (conStr == null || conStr.isEmpty()) {
// return;
// }
LogInfo info = new LogInfo(happenobj).setMsg(msg).setException(exception);
String sql = String.format(
"insert into %s (level, operatorId, operatorName, dllcoid, className, method, args, passTime, msg) " +
"values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'); select @@identity;",
"p_sysWebProLogTab",
level,
info.getUserFId(),
info.getOperatorName(),
dllcoid,
info.getClassname(),
method,
args.replace("'", "\""),
passT,
msg.replace("'", "\"")
);
// if (dbOperator.hasLogTab())
if (NativeExtensionUtils.isNullOrEmpty(jdbcTemplate)) {
DateTimeUtil.setTimeOut(() -> {
try {
// DbOperator _dbOperator = new DbOperator(jdbcTemplate);
String id = jdbcTemplate.queryForObject(sql, String.class) + "";
if ("error".equals(level)) {
error(happenobj, "请到日志表p_sysWebProLogTab中查看详细信息,日志id" + id);
}
} catch (Exception ignored) {
}
}, 1);
} else if ("error".equals(level) && (new Date().getTime() - lastCheckDate.getTime()) > 600000) {
lastCheckDate = new Date();
error(happenobj, "日志表p_sysWebProLogTab未创建,请先创建,然后重启应用程序,再在日志表中查看详细信息!创建语句如下:\n" +
"CREATE TABLE [dbo].[p_sysWebProLogTab](\n" +
" [id] [bigint] PRIMARY KEY IDENTITY(1,1) NOT NULL,\n" +
" [level] varchar(10),\n" +
" [className] varchar(100),\n" +
" [operatorId] varchar(100),\n" +
" [operatorName] varchar(100),\n" +
" [dllcoId] varchar(100) NULL,\n" +
" [passTime] decimal(18,2) NULL,\n" +
" [method] varchar(100) NULL,\n" +
" [args] text NULL,\n" +
" [msg] text NULL,\n" +
" [happenTime] datetime not NULL default getdate())");
}
}
static class LogInfo {
private final Object happenobj;
private Object msg;
private Exception exception;
private String classname;
private LoginUserInfo user;
private String userId;
public LogInfo(Object happenobj) {
this.happenobj = happenobj;
}
public LogInfo setMsg(Object msg) {
this.msg = msg;
return this;
}
public LogInfo setException(Exception exception) {
this.exception = exception;
return this;
}
public String getClassname() {
if (classname == null && happenobj != null) {
String hname = happenobj.getClass().getName();
String[] parts = hname.split("\\.");
hname = parts[parts.length - 1];
if (!hname.isEmpty()) {
classname = hname.substring(0, 1) +
hname.substring(hname.length() - 2, hname.length() - 1) +
"_" + hname.length();
classname = classname.toUpperCase();
} else {
classname = "";
}
}
return classname;
}
private LoginUserInfo getUser() {
if (user == null) {
if (happenobj != null) {
try {
Field field = happenobj.getClass().getDeclaredField("user");
field.setAccessible(true);
user = (LoginUserInfo) field.get(happenobj);
} catch (Exception ignored) {
}
}
if (user == null) {
user = new BaseImpl().getUser();
}
}
return user;
}
public String getUserId() {
if (userId == null) {
String actualUserId = getUserFId();
if (actualUserId != null && !actualUserId.isEmpty()) {
userId = actualUserId.substring(0, 1) +
"**************************".substring(0, actualUserId.length() - 1);
userId = userId.toUpperCase();
} else {
userId = "";
}
}
return userId;
}
public String getUserFId() {
if (userId == null) {
LoginUserInfo u = getUser();
if (u != null) {
userId = u.UserId != null ? u.UserId : u.UserName;
} else {
userId = "";
}
}
return userId;
}
public String getOperatorName() {
LoginUserInfo u = getUser();
if (u != null) {
return u.UserName != null ? u.UserName : u.UserId;
}
return "";
}
public String getOperatorId() {
String name = getOperatorName();
if (!name.isEmpty()) {
return name.substring(0, 1) +
"**************************".substring(0, name.length() - 1);
}
return "";
}
@Override
public String toString() {
return msg != null ? msg.toString() : "";
}
}
}
@@ -0,0 +1,59 @@
package org.example.Api;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import org.example.Impl.BaseImpl;
import org.example.Impl.OptBaseImpl;
import org.example.Impl.Sql.factory.AllInOneSqlFactory;
import org.example.ModuleApi.ModuleAjaxApi.mapper.CRMapper;
import org.example.ModuleApi.ModuleAjaxApi.mapper.DMCrmMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import java.io.IOException;
public class OptBaseHandler extends BaseHandler {
@Autowired
protected JdbcTemplate jdbcTemplate;
@Value("${custom.database.type}")
protected String databaseType;
@Autowired
AllInOneSqlFactory allInOneSqlFactory;
@Autowired
protected CRMapper crmapper;
@Autowired
protected DMCrmMapper DMCrmMapper;
private BaseImpl _opbImpl = null;
@Override
protected void initSystemParams(HttpServletRequest ctx) {
super.initSystemParams((HttpServletRequest) ctx);
_opbImpl = null;
}
@Override
protected BaseImpl getBImpl() {
// 延迟初始化:如果_opbImpl为null,则创建OptBaseImpl实例并赋值
if (_opbImpl == null) {
_opbImpl = new OptBaseImpl(jdbcTemplate, databaseType, allInOneSqlFactory, crmapper, DMCrmMapper);
}
return _opbImpl;
}
}
@@ -0,0 +1,40 @@
package org.example.Api;
import java.util.Map;
import java.util.Set;
public final class PublicApiRegistry {
private static final Map<String, Set<String>> PUBLIC_METHODS = Map.of(
"org.example.Auth.controller.AuthController", Set.of(
"Login",
"ResetPwdByVerify",
"CheckLogin",
"GetUserByName",
"GenerateCaptcha",
"SendPhoneCode",
"verifyCode",
"GetPhoneNumber",
"ResetPwdByPhone"
),
"org.example.SystemApi.controller.SystemAjaxApi", Set.of(
"GetSystemInfo",
"GetEmaUrl",
"GetSystemLoginInfo",
"GetProSysType",
"GetDbServer",
"GetWebUpdateInfo"
)
);
private PublicApiRegistry() {
}
public static boolean isPublicEndpoint(Class<?> handlerType, String methodName) {
if (handlerType == null || methodName == null || methodName.isBlank()) {
return false;
}
Set<String> methods = PUBLIC_METHODS.get(handlerType.getName());
return methods != null && methods.contains(methodName);
}
}
@@ -0,0 +1,264 @@
package org.example.Api;
import org.example.Enums.SystemTypeEnums;
import org.example.Utils.AESUtil;
import org.example.Utils.GZipUtil;
import org.example.Impl.BaseImpl;
import jakarta.servlet.http.HttpServletRequest;
import org.example.Utils.JSON;
import org.example.Utils.WebConfigUtil_web;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Hashtable;
/**
* ==============================================================================
* 功能描述:RequestHandler
* ==============================================================================
*/
public class RequestHandler {
protected Hashtable<String, Object> requestPms;
protected Hashtable<String, Object> zipedPms;
public RequestHandler() {
requestPms = new Hashtable<>();
initPms();
}
/**
* 重置form表单参数
*/
protected void initPms() {
zipedPms = null;
try {
String pms = request("pms");
// out.println(pms + " 1pms");
if (pms != null && !pms.isEmpty()) {
try {
if (pms.contains("%")) {
pms = java.net.URLDecoder.decode(pms, StandardCharsets.UTF_8);
}
requestPms = (Hashtable<String, Object>) JSON.Decode(AESUtil.mobileDecrypt(pms), Hashtable.class);
if (requestPms != null && !requestPms.isEmpty()) {
Hashtable<String, Object> temp = new Hashtable<>();
for (String key : requestPms.keySet()) {
String lkey = key.toLowerCase();
temp.put(lkey, requestPms.get(key));
}
requestPms = temp;
}
} catch (Exception e) {
// 异常处理,可根据需要添加日志
}
}
if (requestPms == null) {
requestPms = new Hashtable<>();
}
} catch (Exception e) {
// 异常处理,可根据需要添加日志
}
}
public void clearPms() {
BaseImpl.setSessionVal(WebConfigUtil_web.Session_Request, "");
}
/**
* 经过压缩后的参数
*/
protected Hashtable<String, Object> getZipedPms() {
if (zipedPms != null) {
return zipedPms;
}
if (isContentZiped()) {
HttpServletRequest request = getHttpServletRequest();
try (Reader reader = new InputStreamReader(request.getInputStream(), request.getCharacterEncoding())) {
StringBuilder contentBuilder = new StringBuilder();
char[] buffer = new char[1024];
int bytesRead;
while ((bytesRead = reader.read(buffer)) != -1) {
contentBuilder.append(buffer, 0, bytesRead);
}
String content = contentBuilder.toString();
if (content != null && !content.isEmpty()) {
BaseImpl.setSessionVal(WebConfigUtil_web.Session_Request, content);
} else {
Object sessionContent = BaseImpl.getSessionVal(WebConfigUtil_web.Session_Request);
content = sessionContent != null ? sessionContent.toString() : "";
}
byte[] buf = java.util.Base64.getDecoder().decode(content);
content = java.net.URLDecoder.decode(GZipUtil.unZip(buf), StandardCharsets.UTF_8);
if (content != null && !content.isEmpty()) {
zipedPms = (Hashtable<String, Object>) JSON.Decode(content, Hashtable.class);
if (zipedPms != null && !zipedPms.isEmpty()) {
Hashtable<String, Object> temp = new Hashtable<>();
for (String key : zipedPms.keySet()) {
temp.put(key.toLowerCase(), zipedPms.get(key));
}
zipedPms = temp;
return temp;
}
}
} catch (IOException e) {
// 异常处理,可根据需要添加日志
}
}
return null;
}
protected void setRequestPms(String key, String val) {
requestPms.put(key, val);
}
/**
* 客户端类型
*/
private int clinetType;
public int getClinetType() {
return SystemTypeEnums.LoginType.Web.getValue();
}
public void setClinetType(int clinetType) {
this.clinetType = clinetType;
}
public SystemTypeEnums.LoginType getLgType() {
try {
return SystemTypeEnums.LoginType.valueOf(String.valueOf(getClinetType()));
} catch (IllegalArgumentException e) {
return SystemTypeEnums.LoginType.Web;
}
}
/**
* 内容编码类型
*/
private String getContentEncoding() {
HttpServletRequest request = getHttpServletRequest();
return request != null ? request.getHeader("Content-Encoding") : null;
}
/**
* webrequest的内容是否是压缩过的
*/
private boolean isContentZiped() {
String contentEncoding = getContentEncoding();
return contentEncoding != null &&
(contentEncoding.contains("gzip") || contentEncoding.contains("deflate"));
}
/**
* 获取表单参数
*
* @param key 表单键
* @param defaultVal 默认值
* @return 参数值
*/
public String request(String key, String defaultVal) {
key = key.toLowerCase(); // 参数不区分大小写
String val = null;
try {
HttpServletRequest request = getHttpServletRequest();
if (request == null) {
return defaultVal;
}
} catch (Exception e) {
// 在程序未初始化完成时访问会报错
return defaultVal;
}
Hashtable<String, Object> ziped = getZipedPms();
if (ziped != null && ziped.containsKey(key)) {
val = String.valueOf(ziped.get(key));
}
if ((val == null || val.isEmpty()) && requestPms.containsKey(key)) {
val = String.valueOf(requestPms.get(key));
}
if (val == null || val.isEmpty()) {
HttpServletRequest request = getHttpServletRequest();
val = request != null ? request.getParameter(key) : null;
if ((val == null || val.isEmpty()) && !key.isEmpty()) {
Enumeration<String> paramNames = null;
if (request != null) {
paramNames = request.getParameterNames();
}
if (paramNames != null) {
while (paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
if (paramName.equalsIgnoreCase(key)) {
val = request.getParameter(paramName);
break;
}
}
}
}
if (val == null || val.isEmpty()) {
val = defaultVal;
}
}
return val;
}
public String request(String key) {
return request(key, "");
}
public String pmsRequest(String key, String defaultVal) {
String val = null;
if (requestPms.containsKey(key)) {
val = String.valueOf(requestPms.get(key));
}
return val != null ? val : defaultVal;
}
public String pmsRequest(String key) {
return pmsRequest(key, "");
}
public Hashtable<String, Object> getAllRequest() {
Hashtable<String, Object> req = new Hashtable<>();
HttpServletRequest request = getHttpServletRequest();
if (request == null) {
return req;
}
// 添加查询参数
Enumeration<String> queryParams = request.getParameterNames();
while (queryParams.hasMoreElements()) {
String key = queryParams.nextElement();
if (key != null && !key.isEmpty()) {
req.put(key, request.getParameter(key));
}
}
return req;
}
/**
* 获取当前请求对象
*/
protected HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
}
@@ -0,0 +1,265 @@
package org.example.Api;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import org.example.Entity.System.LoginUserInfo;
import org.example.Utils.CacheUtil;
import org.example.Utils.WebConfigUtil_web;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.Serializable;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import static org.example.Utils.NativeExtensionUtils.toBoolean;
@Component
public class SingleUserHandler {
// 登录状态枚举
public enum UserLoginState {
LOGIN(1), UNLOGIN(2), WAIT_LOGIN_OUT(3);
private final int value;
UserLoginState(int value) {
this.value = value;
}
}
// 关键修改:缓存存储 全局 LoginUserInfo + 状态 + SessionId(用Map封装)
private static class CacheUserInfo implements Serializable {
private static final long serialVersionUID = 1L;
private LoginUserInfo loginUserInfo; // 全局用户信息(🔥 改动:替换内部类,使用全局LoginUserInfo
private UserLoginState state;
private String sessionId;
// 无参构造 + getter/setter(支持Jackson序列化)
public CacheUserInfo() {
}
public CacheUserInfo(LoginUserInfo loginUserInfo, UserLoginState state, String sessionId) {
this.loginUserInfo = loginUserInfo;
this.state = state;
this.sessionId = sessionId;
}
// getter 方法(🔥 改动:补全序列化必需的getter,否则Jackson无法读取字段)
public LoginUserInfo getLoginUserInfo() {
return loginUserInfo;
}
public UserLoginState getState() {
return state;
}
public String getSessionId() {
return sessionId;
}
// 🔥 改动:补全setter,用于修改状态和SessionId
public void setState(UserLoginState state) {
this.state = state;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
}
private static boolean getUseSingleUser() {
// 每次调用都会重新执行 WebConfigUtil_web.get,拿到最新值
return toBoolean(WebConfigUtil_web.get("SingleUser", ""));
}
public static String cacheKey = "loginDict";
private static RedisTemplate<String, Object> redisTemplate; // 用Redis替代原C#的CacheUtil
private static final ReentrantLock lock = new ReentrantLock(); // 替代lock语句
// 获取登录用户字典
// 获取登录用户字典
@SuppressWarnings("unchecked")
private static Map<String, CacheUserInfo> getInfoDict() {
Object obj = CacheUtil.get(cacheKey);
if (obj == null || !(obj instanceof Map)) {
return new HashMap<>();
}
// Map<String, Object> rawMap = (Map<String, Object>) obj;
// Map<String, CacheUserInfo> resultMap = new HashMap<>();
//
// // 🔥 关键修改:不用 new ObjectMapper(),用 CacheUtil 里配置好的 OBJECT_MAPPER
// ObjectMapper mapper = CacheUtil.OBJECT_MAPPER;
//
// for (Map.Entry<String, Object> entry : rawMap.entrySet()) {
// String sessionId = entry.getKey();
// Object value = entry.getValue();
// if (value instanceof LinkedHashMap) {
// // 现在用的是带“忽略大小写”配置的 mapper,能识别 userId -> UserId
// CacheUserInfo cacheUserInfo = mapper.convertValue(value, CacheUserInfo.class);
// resultMap.put(sessionId, cacheUserInfo);
// }
// }
//
// System.out.println("【getInfoDict】转换后的缓存大小:" + resultMap.size());
return (Map<String, CacheUserInfo>) obj;
}
// 添加登录用户(新登录会踢掉旧登录)
// 🔥 改回:参数恢复为String username(适配其他地方的调用,传的是从实例里拿的UserId/UserName
public static void add(String sessionId, String username) {
// 🔥 改回:恢复原有参数校验(去掉luser非空校验)
if (StringUtils.isEmpty(sessionId) || StringUtils.isEmpty(username) || !getUseSingleUser()) return;
lock.lock();
try {
Map<String, CacheUserInfo> dict = getInfoDict();
// 🔥 逻辑不变:按username(实际是UserId)查询(统一标识字段)
CacheUserInfo cacheUserInfo = getLoginUser(username);
if (cacheUserInfo == null) {
// 🔥 适配:创建全局LoginUserInfo实例,设置UserId为username(其他字段保持默认)
LoginUserInfo loginUserInfo = new LoginUserInfo();
loginUserInfo.UserId = username; // 核心:把传入的username(UserId)赋值给全局用户实例
// 实例化CacheUserInfo,封装全局LoginUserInfo+状态+SessionId
cacheUserInfo = new CacheUserInfo(loginUserInfo, UserLoginState.LOGIN, sessionId);
} else {
dict.remove(cacheUserInfo.getSessionId()); // 移除旧会话
cacheUserInfo.setState(UserLoginState.LOGIN); // 更新状态
cacheUserInfo.setSessionId(sessionId); // 更新SessionId
}
dict.put(sessionId, cacheUserInfo);
// 缓存2小时
// redisTemplate.opsForValue().set(cacheKey, dict, 2, TimeUnit.HOURS);
CacheUtil.set(cacheKey, dict, Duration.ofDays(2), null);
} finally {
lock.unlock();
}
}
// 移除会话
public static void remove(String sessionId) {
if (StringUtils.isEmpty(sessionId) || !getUseSingleUser()) return;
lock.lock();
try {
Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动:适配CacheUserInfo类型
dict.remove(sessionId);
// redisTemplate.opsForValue().set(cacheKey, dict, 2, TimeUnit.HOURS);
CacheUtil.set(cacheKey, dict, Duration.ofDays(2), null);
} finally {
lock.unlock();
}
}
// 标记用户为未登录状态
public static void unLogin(String sessionId) {
if (StringUtils.isEmpty(sessionId) || !getUseSingleUser()) return;
lock.lock();
try {
Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动:适配CacheUserInfo类型
if (dict.containsKey(sessionId)) {
dict.get(sessionId).setState(UserLoginState.UNLOGIN); // 🔥 改动:用setter修改状态
// redisTemplate.opsForValue().set(cacheKey, dict, 2, TimeUnit.HOURS);
CacheUtil.set(cacheKey, dict, Duration.ofDays(2), null);
}
} finally {
lock.unlock();
}
}
// 标记用户为等待登出状态
public static void waitLoginOut(String sessionId) {
if (StringUtils.isEmpty(sessionId) || !getUseSingleUser()) return;
lock.lock();
try {
Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动:适配CacheUserInfo类型
if (dict.containsKey(sessionId)) {
dict.get(sessionId).setState(UserLoginState.WAIT_LOGIN_OUT); // 🔥 改动:用setter修改状态
// redisTemplate.opsForValue().set(cacheKey, dict, 2, TimeUnit.HOURS);
CacheUtil.set(cacheKey, dict, Duration.ofDays(2), null);
}
} finally {
lock.unlock();
}
}
// 根据用户名查询登录信息
// 🔥 改动:参数保持String userId(实际传入的是username=UserId),按UserId查询
private static CacheUserInfo getLoginUser(String userId) {
if (StringUtils.isEmpty(userId) || !getUseSingleUser()) return null;
lock.lock();
try {
Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动:适配CacheUserInfo类型
for (CacheUserInfo info : dict.values()) {
// 🔥 改动:按全局LoginUserInfo的UserId匹配(传入的username就是UserId
if (userId.equals(info.getLoginUserInfo().getUserId())) {
return info;
}
}
return null;
} finally {
lock.unlock();
}
}
// 检查用户是否已登录
// 🔥 改动:参数保持String userId(适配外部调用,传的是UserId)
public static boolean hasLoginUser(String userId) {
if (!getUseSingleUser()) return false;
CacheUserInfo info = getLoginUser(userId); // 🔥 改动:适配新的getLoginUser返回值
return info != null && info.getState() == UserLoginState.LOGIN; // 🔥 改动:用getter获取状态
}
// 检查会话是否存在
public static boolean hasSessionUser(String sessionId) {
if (!getUseSingleUser()) return false;
Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动:适配CacheUserInfo类型
return dict.containsKey(sessionId);
}
/**
* 检查指定会话是否处于未登录状态
*
* @param sessionId 会话ID
* @return 若启用单用户登录且会话存在且状态为未登录,返回true;否则返回false
*/
public static boolean hasUnLoginUser(String sessionId) {
if (getUseSingleUser()) {
Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动:适配CacheUserInfo类型
if (dict != null && dict.containsKey(sessionId)) {
// 注意:需确保LoginUserInfo中存在对应的状态枚举(此处假设已定义)
return dict.get(sessionId).getState() == UserLoginState.UNLOGIN; // 🔥 改动:用getter获取状态
}
}
return false;
}
/**
* 检查指定会话是否处于等待登出状态
*
* @param sessionId 会话ID
* @return 若启用单用户登录且会话存在且状态为等待登出,返回true;否则返回false
*/
public static boolean hasWaitUnLoginUser(String sessionId) {
if (getUseSingleUser()) {
Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动:适配CacheUserInfo类型
if (dict != null && dict.containsKey(sessionId)) {
return dict.get(sessionId).getState() == UserLoginState.WAIT_LOGIN_OUT; // 🔥 改动:用getter获取状态
}
}
return false;
}
}
@@ -0,0 +1,78 @@
package org.example.Auth.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// 权限设定
http.csrf(csrf -> csrf
// 忽略指定接口的CSRF保护
.ignoringRequestMatchers(
"/Api/FileUploadApi",
"/Api/SystemAjaxApi",
"/Api/ModuleAjaxApi",
"/Api/SysUserAjaxApi",
"/Api/ToolsHandler"
)
)
.authorizeHttpRequests(auth -> auth
// 仅开放指定的Api路径,允许所有访问
.requestMatchers(
// "/Api/FileUploadApi/**",
// "/Api/SystemAjaxApi/**",
// "/Api/ModuleAjaxApi/**",
// "/Api/SysUserAjaxApi/**",
// "/Api/ToolsHandler/**",
// "/Api/FileUploadApi",
"/Api/FileUploadApi/**",
"/Api/SystemAjaxApi",
"/Api/SystemAjaxApi/**",
"/Api/ModuleAjaxApi",
"/Api/ModuleAjaxApi/**",
"/Api/SysUserAjaxApi",
"/Api/SysUserAjaxApi/**",
"/Api/ToolsHandler",
"/Api/ToolsHandler/**"
).permitAll()
// 其他所有请求均拒绝访问(或根据需求调整为authenticated()
.anyRequest().denyAll()
);
// .csrf(csrf -> csrf
// .ignoringRequestMatchers(
// "/auth/login",
// "/auth/checklogin",
// "/auth/resetPwd",
// "/auth/users"
// )
// )
// .authorizeHttpRequests(auth -> auth
// // 公开路径,无需认证
// .requestMatchers(
// "/auth/**", // 所有认证相关接口
// "/system/**", // 公开资源
// "/module/**", // 静态资源
// "/error",
// "/Api/FileUploadApi",
// "/Api/SystemAjaxApi",
// "/Api/ModuleAjaxApi"
// ).permitAll()
// // 其他所有请求需要认证
// .anyRequest().authenticated()
// );
// .formLogin(form -> form
// .loginPage("/login")
// .permitAll()
// )
// .logout(logout -> logout
// .permitAll()
// );
return http.build();
}
}
@@ -0,0 +1,246 @@
package org.example.Auth.controller;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.example.Api.BaseHandler;
import org.example.Api.OptBaseHandler;
import org.example.Entity.Attributes.RequestCheck;
import org.example.Entity.Attributes.RequestCheckAttribute;
import org.example.Entity.BaseResponse.BaseResponse;
import org.example.Enums.SystemTypeEnums;
import org.example.Impl.BaseImpl;
import org.example.Impl.SMSImpl;
import org.example.Impl.SysUserImpl;
import org.example.Service.AuthService;
import org.example.Auth.utils.JwtUtils;
import org.example.Auth.utils.SafetyUtil;
import org.example.Entity.System.LoginUserInfo;
import org.example.Utils.DataTableUtil;
import org.example.Utils.DbOperator;
import org.example.Utils.JwtHelp;
import org.example.Utils.NativeExtensionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Objects;
import static org.example.Enums.SystemTypeEnums.LoginType.Web;
import static org.example.Utils.NativeExtensionUtils.ToInt32;
@RestController
@RequestMapping("/Api/SysUserAjaxApi")
public class AuthController extends OptBaseHandler {
@RequestMapping(value = "/**", method = {RequestMethod.GET, RequestMethod.POST})
public void handleRequest(HttpServletRequest Request, HttpServletResponse response) throws Exception {
// 调用 BaseHandler 的 processRequest 处理逻辑
super.processRequest(Request);
}
@Autowired
private AuthService authService;
@Autowired
SysUserImpl userOperator;
protected void InitSystemParams(HttpServletRequest ctx) {
super.initSystemParams(ctx);
}
@RequestCheck(
CheckLogin = false, // 登录不需要先登录
CheckParams = "username|phone", // 必须传递username或phone
Log = true // 打印日志
)
//对应c#的login
public void Login() {
BaseImpl bImpl = getBImpl();
String loginAccount = bImpl.Request("username"), pwd = bImpl.Request("password"), phone = bImpl.Request("phone"), phonecode = bImpl.Request("phonecode"), seriesId = bImpl.Request("seriesId"), serverId = bImpl.Request("server"), gtClientInfo = bImpl.Request("OsClientInfo");
// 1. 优先走「手机号+验证码」登录(与 C# 分支逻辑一致)
if (!NativeExtensionUtils.isNullOrEmpty(phone) && !NativeExtensionUtils.isNullOrEmpty(phonecode)) {
// 调用手机号登录方法(需确保 AuthService 有此方法,参数匹配)
response = userOperator.LoginByPhone(phone, phonecode,loginAccount,null);
}
// 2. 其次走「账号+密码」登录(C# 中固定 LoginType.WebIP 传 null
else if (!NativeExtensionUtils.isNullOrEmpty(loginAccount)) {
// 参数对应 C#loginAccount, pwd, seriesId, serverId.ToInt32(), LoginType.Web, null, gtClientInfo
response = userOperator.Login(
loginAccount,
pwd,
seriesId,
ToInt32(serverId),
Web, // 与 C# LoginType.Web 对齐,需确保枚举值存在
null, // C# 中此参数传 null,对应 Java 接口的 ip 参数
gtClientInfo // 对应 C# 的 gtClientInfo
);
}
}
public void ChangeServer() {
BaseResponse[] response = new BaseResponse[1];
response[0] = new BaseResponse();
BaseImpl bImpl = getBImpl();
int serverId = ToInt32(bImpl.Request("server"));
StringBuilder errMsg;
errMsg = new StringBuilder();
DbOperator dbOper = userOperator.ChangeServer(serverId, errMsg);
if (dbOper != null && serverId != getUser().ServerId) {
bImpl.sysLog(String.format("{0}切换账套{1}=>{2}", getUser().UserName, getUser().ServerId, serverId), "切换账套");
getUser().ConnectionString = dbOper.getConnectionString();
getUser().ServerId = serverId;
LoginUserInfo _user = userOperator.OnLoginSuccess(null, getUser(), getUser().SeriesId, getUser().ServerId, getUser().UserId, dbOper.getConnectionString(), response[0], true);
BaseImpl.setSessionVal(getUserSessionName(), _user);
if (!NativeExtensionUtils.isNullOrEmpty(getDriver()) && (Objects.equals(getDriver(), "android") || Objects.equals(getDriver(), "ios"))) {
response[0].setToken(JwtHelp.createToken(_user, 2592000));//过期时间30天
} else {
response[0].setToken(JwtHelp.createToken(_user, 3600));
BaseImpl.setSessionVal(getUserSessionName(), _user);
}
response[0].setSuccess(true);
} else {
response[0].setMsg("切换失败:{"+errMsg+"}!");
}
super.response=response[0];
}
//对应c#的getseverName,上面的那个ChangeServer牵涉到数据库的切换,所有关于数据库切换的都没整
public void GetServerName() {
response.setData(userOperator.GetCurrentServerName());
response.setSuccess(true);
}
@RequestCheck(CheckParams = "oldpassword|newpassword|renewpassword")
//对应restpwd
public void ResetPwd() {
BaseImpl bImpl = getBImpl();
String oldPwd = bImpl.Request("oldpassword"), newPwd = bImpl.Request("newpassword"), renewPwd = bImpl.Request("renewpassword");
response = userOperator.ResetPwd(oldPwd, newPwd, renewPwd);
}
@RequestCheck(CheckParams = "newpassword|renewpassword")
//对应restpwdcomp
public void ResetPwdComp() {
BaseImpl bImpl = getBImpl();
String newPwd = bImpl.Request("newpassword"), renewPwd = bImpl.Request("renewpassword");
response = userOperator.ResetPwdComp(newPwd, renewPwd);
}
//新增
@RequestCheck(CheckParams = "newpassword|renewpassword", CheckLogin = false)
//ResetPwdByVerify
public void ResetPwdByVerify() {
BaseImpl bImpl = getBImpl();
String newPwd = bImpl.Request("newpassword"), renewPwd = bImpl.Request("renewpassword"),uuid = bImpl.Request("codeuuid");
response = userOperator.ResetPwdCompByverify(newPwd, renewPwd,uuid);
}
public void InitializePwd() {
BaseImpl bImpl = getBImpl();
String oldPwd = bImpl.Request("username"), newPwd = bImpl.Request("newpassword"), renewPwd = bImpl.Request("renewpassword");
response = userOperator.InitializePwd(oldPwd, newPwd, renewPwd);
}
/**
* 登出接口
* 无需请求体参数,通过请求头中的 Token 识别用户
*/
@RequestCheck(
CheckLogin = true, // 登出需要先登录
CheckParams = "", // 不校验参数
Log = false // 不打印日志
)
public void LoginOut() {
BaseImpl bImpl = getBImpl();
int delay = ToInt32(bImpl.Request("delay"));
if (delay <= 0 && bImpl.isPhone()) {
userOperator.LoginOut();
}
super.loginOut();
}
@RequestCheck(CheckLogin = false)
public boolean CheckLogin() {
boolean ok = super.checkLogin();
if (ok && getBImpl().isPhone() && getBImpl().getAppVersion() > 0) {
userOperator.UpdOsVersion();
}
return ok;
}
@RequestCheck(CheckLogin = false)
public void GetUserByName() {
String LoginAccount = getBImpl().Request("username");
response.setData(userOperator.GetUserByName(LoginAccount, ""));
response.setSuccess(response.getData() != null);
}
@RequestCheck(CheckParams = "userid")
public void GetGPSLoction() {
BaseImpl bImpl = getBImpl();
String userid = bImpl.Request("userid"), lasttime = bImpl.Request("lasttime");
lasttime = NativeExtensionUtils.isNullOrEmpty(lasttime) ? LocalDate.now().atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : lasttime;
response = userOperator.GetGPSLoction(userid, lasttime);
}
@RequestCheck(CheckLogin = false)
public void GenerateCaptcha(){
BaseImpl bImpl = getBImpl();
String captchaCodeKey = bImpl.Request("captchaCodeKey");
response = userOperator.GenerateCaptcha(captchaCodeKey);
}
@RequestCheck(CheckLogin = false)
public void SendPhoneCode()
{
BaseImpl bImpl = getBImpl();
SMSImpl sMSImpl = new SMSImpl();
String phoneNumber= bImpl.Request("phone");
String phonecode = bImpl.Request("phonecode");
String imageCode = bImpl.Request("code");
String codeKey = bImpl.Request("codekey");
response = sMSImpl.sendPhoneCode(phoneNumber,phonecode,imageCode, codeKey);
}
@RequestCheck(CheckLogin = false)
public void verifyCode()
{
BaseImpl bImpl = getBImpl();
String phoneNumber = bImpl.Request("phone");
String phoneCode = bImpl.Request("phonecode");
String username = bImpl.Request("username");
String uuid = bImpl.Request("codeuuid");
response = userOperator.verifyCode(phoneNumber,phoneCode, username, uuid);
}
@RequestCheck(CheckLogin = false)
public void GetPhoneNumber()
{
BaseImpl bImpl = getBImpl();
String username = bImpl.Request("username");
response = userOperator.GetPhoneNumber(username);
}
@RequestCheck(CheckLogin = false)
public void ResetPwdByPhone()
{
response = userOperator.ResetPwdByPhone();
}
}
@@ -0,0 +1,87 @@
package org.example.Auth.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.example.Entity.System.LoginUserInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.nio.file.LinkOption;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Component
public class JwtUtils {
private final SecretKey secretKey;
private final long expiration;
// 使用构造函数注入配置
public JwtUtils(@Value("${jwt.expiration}") long expiration) {
// 生成安全的 512 位密钥
this.secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS512);
this.expiration = expiration;
}
// 生成安全的 HS512 密钥
private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS512);
private static final long EXPIRATION_TIME = 1000 * 60 * 60 * 24; // 24小时
public static String generateToken(Map<String,Object> user) {
Map<String, Object> claims = new HashMap<>();
claims.put("UserId", user.get("UserId"));
claims.put("UserCode", user.get("LoginAccount"));
claims.put("UserName", user.get("EmpLoyeeName"));
claims.put("LoginOs", "web");
claims.put("ServerId", 0);
claims.put("AppIndex", user.get("AppIndex"));
claims.put("ClientId", user.get("p_emp_clientid"));
claims.put("AttendanceTime", user.get("p_emp_AttendanceTime"));
claims.put("SeriesId",user.getOrDefault("p_emp_SeriesId",0));
return Jwts.builder()
.setClaims(claims)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SECRET_KEY, SignatureAlgorithm.HS512)
.compact();
}
public static boolean validateToken(String token) {
try {
Claims claims = Jwts.parserBuilder()
.setSigningKey(SECRET_KEY)
.build()
.parseClaimsJws(token)
.getBody();
Date expirationDate = claims.getExpiration();
Date now = new Date();
return expirationDate != null && expirationDate.after(now);
} catch (Exception e) {
return false;
}
}
// 从令牌中获取用户名
public static String getUsernameFromToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(SECRET_KEY)
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
}
// 新增公共方法:从 Token 中获取 claims
public Claims getClaimsFromToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(secretKey)
.build()
.parseClaimsJws(token)
.getBody();
}
}
@@ -0,0 +1,52 @@
package org.example.Auth.utils;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.springframework.stereotype.Component;
@Component
public class SafetyUtil {
// 加密密码
/**
* 密码加密加密(对应C#的SHA1加密实现)
*
* @param strPassword 原始密码
* @return 加密后的密码字符串
*/
public static String encryptPassword(String strPassword) {
// 拼接C#中的String.Format("2006{0}New System", strPassword)
String formattedPassword = String.format("2006%sNew System", strPassword);
try {
// 获取SHA1加密实例(对应C#的SHA1CryptoServiceProvider
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
// 转换为ASCII字节数组(与C# Encoding.ASCII.GetBytes保持一致)
byte[] bytes = formattedPassword.getBytes(StandardCharsets.US_ASCII);
// 计算哈希值
byte[] hashBytes = sha1.digest(bytes);
// 转换为十六进制字符串(对应C# BitConverterBitConverter.ToString并去除横杠)
StringBuilder hexString = new StringBuilder();
for (byte b : hashBytes) {
// 格式C#格式保持一致,不足两位两位则补0
hexString.append(String.format("%02X", b));
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
// 保持与C#一致的异常处理风格
throw new RuntimeException("SHA-1算法算法不支持", e);
}
}
// 验证密码
public boolean verifyPassword(String rawPassword, String encodedPassword) {
String encryptedRawPassword = encryptPassword(rawPassword);
return encryptedRawPassword.equals(encodedPassword);
}
}
@@ -0,0 +1,51 @@
package org.example.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 1. 允许的前端源(必须指定具体地址,不能用*,否则Cookie无法携带)
config.addAllowedOriginPattern("http://localhost:14564");
config.addAllowedOriginPattern("http://localhost:8082");
config.addAllowedOriginPattern("http://localhost:8081");
config.addAllowedOriginPattern("http://127.0.0.1:8081");
config.addAllowedOriginPattern("http://192.168.1.51:8081");
config.addAllowedOriginPattern("http://192.168.1.52:8081");
config.addAllowedOriginPattern("http://192.168.0.162:14564");
config.addAllowedOriginPattern("http://192.168.222.12:8081");
config.addAllowedOriginPattern("http://110.185.161.104:8080");
config.addAllowedOriginPattern("http://222.211.229.79:8081");
// 2. 允许跨域携带Cookie(核心)
config.setAllowCredentials(true);
// 3. 允许的请求方法(GET/POST等)
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("PATCH");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("OPTIONS");
// 4. 允许的请求头(如Content-Type、Authorization等)
config.addAllowedHeader("*");
// 5. 暴露的响应头(前端需要读取的头,如Set-Cookie)
config.addExposedHeader("Authorization");
config.addExposedHeader("Set-Cookie");
config.addExposedHeader("Content-Disposition");
config.addExposedHeader("Content-Length");
config.addExposedHeader("X-Total-Count");
// 新增:优化预检请求缓存时间(减少OPTIONS请求次数,单位:秒)
config.setMaxAge(3600L); // 1小时内不再重复发送预检请求
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// 对所有路径生效
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
@@ -0,0 +1,27 @@
package org.example.Config;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.example.Utils.RequestUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
@Component
public class RequestCleanupFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain
) throws ServletException, IOException {
try {
filterChain.doFilter(request, response);
} finally {
RequestUtil.clear();
}
}
}
@@ -0,0 +1,49 @@
package org.example.Config;
import jakarta.annotation.PostConstruct;
import org.example.Utils.CacheUtil;
import org.example.Utils.JsEngine;
import org.example.Utils.ResourceExecutors;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ResourceGovernanceConfig {
@Value("${app.cache.max-entries:5000}")
private int cacheMaxEntries;
@Value("${app.js-cache.max-entries:1000}")
private int jsCacheMaxEntries;
@Value("${app.executor.file-cleanup.core-size:2}")
private int fileCleanupCoreSize;
@Value("${app.executor.file-cleanup.max-size:4}")
private int fileCleanupMaxSize;
@Value("${app.executor.file-cleanup.queue-capacity:200}")
private int fileCleanupQueueCapacity;
@Value("${app.executor.push.core-size:4}")
private int pushCoreSize;
@Value("${app.executor.push.max-size:16}")
private int pushMaxSize;
@Value("${app.executor.push.queue-capacity:500}")
private int pushQueueCapacity;
@PostConstruct
public void applyResourceGovernanceSettings() {
CacheUtil.setMaxEntries(cacheMaxEntries);
JsEngine.setMaxCacheEntries(jsCacheMaxEntries);
ResourceExecutors.configure(
fileCleanupCoreSize,
fileCleanupMaxSize,
fileCleanupQueueCapacity,
pushCoreSize,
pushMaxSize,
pushQueueCapacity
);
}
}
@@ -0,0 +1,19 @@
package org.example.Config;
import jakarta.annotation.PreDestroy;
import org.example.Utils.DynamicJdbcTemplateRegistry;
import org.example.Utils.FileUtil;
import org.example.Utils.JsEngine;
import org.example.Utils.ResourceExecutors;
import org.springframework.stereotype.Component;
@Component
public class ResourceLifecycleManager {
@PreDestroy
public void shutdownResources() {
FileUtil.shutdownExecutor();
JsEngine.shutdown();
ResourceExecutors.shutdownAll();
DynamicJdbcTemplateRegistry.closeAll();
}
}
@@ -0,0 +1,4 @@
package org.example.Entity.Attributes;
public interface Attribute {
}
@@ -0,0 +1,98 @@
package org.example.Entity.Attributes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class AttributeUtils {
private static final Logger log = LoggerFactory.getLogger(AttributeUtils.class);
/**
* 模拟C#的Attribute.GetCustomAttribute方法
* 从方法或类上获取自定义属性实例
*/
@SuppressWarnings("unchecked")
// public static <T extends Attribute> T getAttribute(Method method, Class<T> attributeClass) {
// // 1. 先从方法的参数上查找(如果有标注)
// List<T> attributes = findAttributes(method.getDeclaringClass(), attributeClass);
// if (!attributes.isEmpty()) {
// return attributes.get(0);
// }
// // 2. 从方法本身查找
// attributes = findAttributes(method, attributeClass);
// return attributes.isEmpty() ? null : attributes.get(0);
// }
public static RequestCheckAttribute getAttribute(Method method) {
// 1. 检查方法上是否有@RequestCheck注解
if (method.isAnnotationPresent(RequestCheck.class)) {
RequestCheck annotation = method.getAnnotation(RequestCheck.class);
return convertAnnotationToAttribute(annotation);
}
// 2. 若方法无注解,检查类上的注解
Class<?> clazz = method.getDeclaringClass();
if (clazz.isAnnotationPresent(RequestCheck.class)) {
RequestCheck annotation = clazz.getAnnotation(RequestCheck.class);
return convertAnnotationToAttribute(annotation);
}
// 3. 若都无注解,返回null(或默认默认配置)
return null;
}
// 将注解转换为RequestCheckAttribute实例
private static RequestCheckAttribute convertAnnotationToAttribute(RequestCheck annotation) {
RequestCheckAttribute attribute = new RequestCheckAttribute();
attribute.CheckLogin = annotation.CheckLogin();
attribute.CheckParams = annotation.CheckParams();
attribute.Log = annotation.Log();
attribute.Verify = annotation.Verify();
attribute.Cache = annotation.Cache();
attribute.ExpirationPeriod = annotation.ExpirationPeriod();
attribute.Name = annotation.Name();
attribute.Desp = annotation.Desp();
return attribute;
}
public static <T extends Attribute> T getCustomAttribute(Class<?> type, Class<T> attributeClass) {
List<T> attributes = findAttributes(type, attributeClass);
return attributes.isEmpty() ? null : attributes.get(0);
}
/**
* 从目标对象(类/方法)中查找自定义属性实例
*/
private static <T extends Attribute> List<T> findAttributes(Object target, Class<T> attributeClass) {
List<T> result = new ArrayList<>();
try {
// 实际项目中可改为:从类的特定字段或注解中解析属性
// 这里模拟通过反射获取预定义的属性实例
if (target instanceof Class<?>) {
Class<?> clazz = (Class<?>) target;
// 查找类中定义的属性实例(例如通过特定命名规范的字段)
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
log.debug(String.valueOf("扫描字段:" + field.getName() + ",类型:" + field.getType().getSimpleName()));
if (attributeClass.isAssignableFrom(field.getType())) {
field.setAccessible(true);
Object value = field.get(null); // 假设是静态字段
if (value != null) {
result.add((T) value);
log.debug(String.valueOf("找到匹配属性:" + field.getName()));
}
}
}
} else if (target instanceof Method) {
Method method = (Method) target;
// 查找方法上的属性实例(例如通过方法参数或注解)
// 这里简化处理,实际可根据需要扩展
}
} catch (Exception e) {
log.error("Exception caught", e);
}
return result;
}
}
@@ -0,0 +1,34 @@
package org.example.Entity.Attributes;
import java.lang.annotation.*;
// 注解作用在方法或类上
@Target({ElementType.METHOD, ElementType.TYPE})
// 注解保留到运行时(框架需要在运行时获取)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestCheck {
// 是否检查登录(默认true,对应RequestCheckAttribute的CheckLogin
boolean CheckLogin() default true;
// 需要校验的参数(对应CheckParams,默认空字符串)
String CheckParams() default "";
// 是否打印日志(对应Log,默认true)
boolean Log() default true;
// 是否验证(对应Verify,默认true)
boolean Verify() default true;
// 是否缓存(对应Cache,默认false)
boolean Cache() default false;
// 缓存过期时间(对应ExpirationPeriod,默认10分钟)
int ExpirationPeriod() default 10;
// 名称和描述(对应Name和Desp)
String Name() default "";
String Desp() default "";
boolean WriteRespose() default true;
}
@@ -0,0 +1,157 @@
package org.example.Entity.Attributes;
import org.example.Api.BaseHandler;
import org.example.Impl.BaseImpl;
import org.example.Impl.VerifyImpl;
import org.example.Utils.CacheUtil;
import org.example.Utils.JSON;
import org.example.Utils.LanguageUtil;
import org.example.Utils.WebConfigUtil_web;
import java.time.Duration;
import java.util.function.Supplier;
import static org.example.Utils.NativeExtensionUtils.isNullOrEmpty;
import static org.example.Utils.NativeExtensionUtils.toBoolean;
/**
* 功能描述:RequestCheckAttribute
* 创 建 者:wzy
* 创建日期:2017-01-05 22:33:06
*/
public class RequestCheckAttribute implements Attribute {
/**
* 是否检查登录信息
*/
public Boolean CheckLogin = true;
/**
* 是否向客户端回写
*/
public Boolean WriteRespose = true;
/**
* 检查request的字段是否为空
*/
public String CheckParams = "";
public boolean Log = true;
public boolean Verify = true;
public boolean Cache = false;
/// <summary>
/// 缓存失效时间,默认30分钟
/// </summary>
public int ExpirationPeriod = 10;
public String Name;
public String Desp;
private VerifyImpl _verifyimpl;
private BaseImpl _bImpl;
private VerifyImpl getVerifyImpl() {
if (_verifyimpl == null) {
_verifyimpl = new VerifyImpl();
}
return _verifyimpl;
}
public BaseImpl getBImpl() {
if (_bImpl == null) {
_bImpl = new BaseImpl();
}
return _bImpl;
}
public void setBImpl(BaseImpl bImpl) {
this._bImpl = bImpl;
}
/**
* 验证参数是否有效
*
* @param errMsg 检查参数配置
* @return 验证结果数组,第一个元素为是否有效,第二个元素为错误信息
*/
public Boolean validParams(String[] errMsg) {
errMsg[0] = "";
if (!isValid()) {
return false;
}
if (isNullOrEmpty(CheckParams)) {
return true;
}
String[] pamNames = CheckParams.split(",");
for (String pamName : pamNames) {
if (pamName == null || pamName.isEmpty()) {
continue;
}
String[] orPamNames = pamName.split("\\|"); // 转义|符号
if (orPamNames.length == 1) {
if (getBImpl().Request(pamName) == null || getBImpl().Request(pamName).isEmpty()) {
errMsg[0] = String.format("%s:%s", LanguageUtil.InvalidParameter, pamName);
return false;
}
} else {
boolean hasVal = false;
for (String orName : orPamNames) {
if (getBImpl().Request(orName) != null && !getBImpl().Request(orName).isEmpty()) {
hasVal = true;
break;
}
}
if (!hasVal) {
errMsg[0] = String.format("%s:%s", LanguageUtil.InvalidParameter, pamName.replace("|", ""));
return false;
}
}
}
return true;
}
/**
* 获取缓存值
*
* @param handler 基础处理器
* @param getCacheValue 获取缓存值的供应商
* @return 缓存值或新生成的值
*/
public Object getCacheVal(BaseHandler handler, Supplier<Object> getCacheValue) {
if (Cache && toBoolean(WebConfigUtil_web.get("Cache", ""))) {
String key = String.valueOf((handler.getClass().getName()
+ "_" + getBImpl().getUser().UserId
+ "_" + getBImpl().getUser().UserName
+ "_" + JSON.Encode(getBImpl().getAllRequest())).hashCode());
// 将Supplier转换为Function<Void, Object>
return CacheUtil.getCacheItem(key,
(Void v) -> getCacheValue.get(), // 适配Function接口
Duration.ofMinutes(ExpirationPeriod),
null, null);
}
return getCacheValue.get();
}
public boolean isValid() {
return validVerify();
}
public boolean validVerify() {
if (!Verify) {
return true;
} else {
return getVerifyImpl().verify().isSuccess();
}
}
}
@@ -0,0 +1,191 @@
package org.example.Entity.BaseResponse;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.example.Utils.NativeExtensionUtils;
import org.example.Utils.WebConfigUtil_web;
import java.util.Hashtable;
import java.util.Map;
/**
* ==============================================================================
* 功能描述:BaseResponse
* ==============================================================================
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class BaseResponse {
/**
* 是否成功
*/
private boolean success;
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
private String sql;
/**
* 文字信息
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private String msg;
/**
* 数据总数
*/
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private int tot = 0;
/**
* 返回的主数据
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private Object data;
/**
* 如有其它数据
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private Object other;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object attc;
@JsonInclude(JsonInclude.Include.NON_NULL)
private String token;
private Boolean sharLogin;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean getSharToken() {
if (token != null && !token.isEmpty()) {
return NativeExtensionUtils.toBoolean(WebConfigUtil_web.get("SharLogin", "1"));
}
return sharLogin;
}
public void setSharToken(Boolean value) {
this.sharLogin = value;
}
/**
* webversion 用于更新前端
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private String webVer;
/**
* json编码后的字符串
*/
@JsonIgnore
private String encodedResult;
/**
* json编码后的字符串
*/
@JsonIgnore
private boolean writeResponse = true;
/**
* webversion 用于更新前端
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private Map<?, ?> printInfo;
// Getters and Setters
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
public int getTot() {
return tot;
}
public void setTot(int tot) {
this.tot = tot;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object getOther() {
return other;
}
public void setOther(Object other) {
this.other = other;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getWebVer() {
return webVer;
}
public void setWebVer(String webVer) {
this.webVer = webVer;
}
@JsonIgnore
public String getEncodedResult() {
return encodedResult;
}
public void setEncodedResult(String encodedResult) {
this.encodedResult = encodedResult;
}
@JsonIgnore
public boolean isWriteResponse() {
return writeResponse;
}
public void setWriteResponse(boolean writeResponse) {
this.writeResponse = writeResponse;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Map<?, ?> getPrintInfo() {
return printInfo;
}
public void setPrintInfo(Map<?, ?> printInfo) {
this.printInfo = printInfo;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Map<String, Object> AppCfg;
}
@@ -0,0 +1,32 @@
package org.example.Entity;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
/**
* 模拟C#的[Cache]注解(基于Spring Cache封装)
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Cacheable
public @interface Cache {
/**
* 缓存过期时间(单位:分钟,仅标记,实际需结合缓存管理器配置)
*/
int ExpirationPeriod() default 10;
/**
* 缓存key(复用Spring Cache的key属性)
*/
@AliasFor(annotation = Cacheable.class, attribute = "key")
String key() default "";
/**
* 缓存名称(复用Spring Cache的value属性)
*/
@AliasFor(annotation = Cacheable.class, attribute = "value")
String[] value() default {"printCache"};
}
@@ -0,0 +1,45 @@
package org.example.Entity.Control.Base;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.example.Entity.System.LoginUserInfo;
import org.example.Impl.BaseImpl;
/**
* ==============================================================================
* 功能描述:基础控件的父类
* ==============================================================================
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Base {
protected String defaultXtype = "box";
// 控件的类型
private String _xtype;
public String getXtype() {
return this._xtype != null ? this._xtype : defaultXtype;
}
public void setXtype(String value) {
_xtype = value;
}
private LoginUserInfo _user;
@JsonIgnore
protected LoginUserInfo getUser() {
if (_user == null)//&& HttpContext.Current != null && HttpContext.Current.Session != null
{
_user = new BaseImpl().getUser(); //HttpContext.Current.Session[Lskj.Web.Core.Util.WebConfigUtil.Session_LoginUser] as LoginUserInfo ?? new LoginUserInfo();
} else {
return new LoginUserInfo();
}
return _user;
}
public void setUser(LoginUserInfo vlaue) {
this._user = vlaue;
}
}
@@ -0,0 +1,139 @@
package org.example.Entity.Control.Base;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Utils.IPublicUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.ArrayList;
import java.util.List;
/**
* ==============================================================================
* 功能描述:Component 所有Ext组件的基类
* ==============================================================================
*/
@org.springframework.stereotype.Component
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Component extends Base {
@JsonIgnore
private IPublicUtil _util;
// 自动注入JdbcTemplate(由Spring容器提供,已关联DataSource
@JsonIgnore
@Autowired
protected JdbcTemplate jdbcTemplate;
@JsonIgnore
protected IPublicUtil getUtil() {
if (_util == null) {
// 若IPublicUtil需要JdbcTemplate,通过构造函数传入已注入的实例
_util = new IPublicUtil(jdbcTemplate);
}
return _util;
}
public void setUtil(IPublicUtil _util) {
this._util = _util;
}
private JdbcTemplate _dbOperator;
@JsonIgnore
protected JdbcTemplate getDbOperator() {
if (_dbOperator == null) {
if (getUtil() != null) {
_dbOperator = _util.GetOperater();
}
}
return _dbOperator;
}
public void setDbOperator(JdbcTemplate value) {
this._dbOperator = value;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer width;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer height;
protected Boolean hidden;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean getHidden() {
return this.hidden;
}
public void setHidden(Boolean hidden) {
this.hidden = hidden;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean disabled;
protected Integer top;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getTop() {
return top;
}
public void setTop(Integer top) {
this.top = top;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getLeft() {
return left;
}
public void setLeft(Integer left) {
this.left = left;
}
protected Integer left;
@JsonInclude(JsonInclude.Include.NON_NULL)
public List<Component> items;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object defaults;
// 添加子组件
public void Add(Component com) {
if (this.items == null) {
this.items = new ArrayList<Component>();
}
this.items.add(com);
}
// 比较组件位置(替代C#的操作符重载)
public static boolean isGreater(Component left, Component right) {
final int err = 5; // +-5px误差
// 处理left.top或right.top为null的情况(例如默认值设为0)
int leftTop = (left.getTop() != null) ? left.getTop() : 0;
int rightTop = (right.getTop() != null) ? right.getTop() : 0;
if (leftTop < rightTop - err) {
return true;
} else if (leftTop >= rightTop - err && leftTop <= rightTop + err) {
// 若top接近,比较left属性(同样处理null)
int leftLeft = (left.getLeft() != null) ? left.getLeft() : 0;
int rightLeft = (right.getLeft() != null) ? right.getLeft() : 0;
return leftLeft < rightLeft;
} else {
return false;
}
}
public static boolean isLess(Component left, Component right) {
return !isGreater(left, right);
}
}
@@ -0,0 +1,30 @@
package org.example.Entity.Control.Base;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.example.Utils.IPublicUtil;
import java.util.Map;
/**
* ==============================================================================
* 功能描述:RowComponent 所有Ext组件的基类,该类值有datarow 提供
* ==============================================================================
*/
public class RowComponent extends Component {
@JsonIgnore
public Map<String, Object> _row;
public RowComponent(Map<String, Object> row) {
super();
this._row = (row);
}
public RowComponent(Map<String, Object> row, IPublicUtil util) {
this(row);
this.setUtil(util);
}
}
@@ -0,0 +1,391 @@
package org.example.Entity.Control.Com;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Base.RowComponent;
import org.example.Utils.DataTableUtil;
import org.example.Utils.IPublicUtil;
import java.util.Map;
import static org.example.Utils.NativeExtensionUtils.toBoolean;
/**
* ==============================================================================
* 功能描述:Button
* ==============================================================================
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Button extends RowComponent {
public Button() {
super(null);
this.defaultXtype = "button";
}
public Button(Map<String, Object> row) {
super(row);
this.defaultXtype = "button";
this._row = row;
}
public Button(Map<String, Object> row, IPublicUtil util) {
super(row, util);
this.defaultXtype = "button";
this._row = row;
this.setUtil(util);
}
private int toolId;
private String cls;
private String iconCls;
private String text;
private Boolean hidden;
private String actionLib;
private String action;
private String beforeMsg;
private String successMsg;
private String errorMsg;
private String handler;
private boolean formBind;
private Object menu;
private String href;
private String pm1;
private String pm2;
private String pm3;
private String pm4;
private String pm5;
private String pm6;
private String pm7;
private String pm8;
private String pm9;
private String pm10;
// 工具ID
public int getToolId() {
if (toolId <= 0 && _row != null) {
toolId = DataTableUtil.getIntValue(_row, "id", 0);
}
return toolId;
}
public void setToolId(int toolId) {
this.toolId = toolId;
}
// CSS类
public String getCls() {
return cls;
}
public void setCls(String cls) {
this.cls = cls;
}
// 图标类
public String getIconCls() {
return iconCls;
}
public void setIconCls(String iconCls) {
this.iconCls = iconCls;
}
// 按钮文本
public String getText() {
if (text == null && _row != null) {
text = DataTableUtil.getStringValue(_row, new String[]{"menucaption", "text"}, null);
}
return text;
}
public void setText(String text) {
this.text = text;
}
private String _recordCond;
// 记录条件
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("RecordCond")
public String getRecordCond() {
if (_recordCond == null && _row != null) {
_recordCond = (String) DataTableUtil.getRowVal(_row, "Menucond", null);
}
return _recordCond;
}
public void setRecordCond(String recordCond) {
this._recordCond = recordCond;
}
// 隐藏状态
public Boolean getHidden() {
return hidden;
}
public void setHidden(Boolean hidden) {
this.hidden = hidden;
}
// 按钮类型
@JsonProperty("BType")
public int getBType() {
return _row != null ? DataTableUtil.getIntValue(_row, "type", 0) : 0;
}
// 动作类型
@JsonProperty("ActionType")
public int getActionType() {
return _row != null ? DataTableUtil.getIntValue(_row, "actiontype", 0) : 0;
}
@JsonIgnore // 动态链接库
public String getActionLib() {
if (actionLib == null && _row != null) {
actionLib = DataTableUtil.getStringValue(_row, "library", null);
}
return actionLib;
}
public void setActionLib(String actionLib) {
this.actionLib = actionLib;
}
@JsonIgnore
// 执行的SQL或存储过程
public String getAction() {
if (action == null && _row != null) {
action = DataTableUtil.getStringValue(_row, "action", null);
}
return action;
}
public void setAction(String action) {
this.action = action;
}
// 执行前提示
public String getBeforeMsg() {
if (beforeMsg == null && _row != null) {
beforeMsg = DataTableUtil.getStringValue(_row, "beforemsg", null);
}
return beforeMsg;
}
public void setBeforeMsg(String beforeMsg) {
this.beforeMsg = beforeMsg;
}
// 执行成功提示
public String getSuccessMsg() {
if (successMsg == null && _row != null) {
successMsg = DataTableUtil.getStringValue(_row, "SuccessMsg", null);
}
return successMsg;
}
public void setSuccessMsg(String successMsg) {
this.successMsg = successMsg;
}
// 执行失败提示
public String getErrorMsg() {
if (errorMsg == null && _row != null) {
errorMsg = DataTableUtil.getStringValue(_row, "ErrorMsg", null);
}
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
// 双击属性
@JsonProperty("DoubleClick")
public boolean isDoubleClick() {
return _row != null && DataTableUtil.getBooleanValue(_row, "DoubleClick", false);
}
// 窗口最大化
@JsonProperty("MaxWindow")
public boolean isMaxWindow() {
return _row != null && DataTableUtil.getBooleanValue(_row, "MaxWindow", false);
}
// 执行后刷新
@JsonProperty("Refresh")
public boolean isRefresh() {
return toBoolean(DataTableUtil.getRowVal(_row, "Refresh", false));
}
// 多选
@JsonProperty("MoreClick")
public boolean isMoreClick() {
return _row != null && DataTableUtil.getBooleanValue(_row, "moreclick", false);
}
// 多选提示
@JsonProperty("MoreClickTip")
public boolean isMoreClickTip() {
return _row != null && DataTableUtil.getBooleanValue(_row, "moreclicktip", false);
}
// 处理函数
public String getHandler() {
return handler;
}
public void setHandler(String handler) {
this.handler = handler;
}
// 表单绑定
public boolean isFormBind() {
return formBind;
}
public void setFormBind(boolean formBind) {
this.formBind = formBind;
}
// 菜单
public Object getMenu() {
return menu;
}
public void setMenu(Object menu) {
this.menu = menu;
}
// 链接
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
// 刷新标志
@JsonProperty("refresh")
public boolean isLowerRefresh() {
return toBoolean(DataTableUtil.getRowVal(this._row, "refresh", true));
}
// 参数1-10的实现
public String getPm1() {
if (pm1 == null && _row != null) {
pm1 = DataTableUtil.getStringValue(_row, "param1", null);
}
return pm1;
}
public void setPm1(String pm1) {
this.pm1 = pm1;
}
public String getPm2() {
if (pm2 == null && _row != null) {
pm2 = DataTableUtil.getStringValue(_row, "param2", null);
}
return pm2;
}
public void setPm2(String pm2) {
this.pm2 = pm2;
}
public String getPm3() {
if (pm3 == null && _row != null) {
pm3 = DataTableUtil.getStringValue(_row, "param3", null);
}
return pm3;
}
public void setPm3(String pm3) {
this.pm3 = pm3;
}
public String getPm4() {
if (pm4 == null && _row != null) {
pm4 = DataTableUtil.getStringValue(_row, "param4", null);
}
return pm4;
}
public void setPm4(String pm4) {
this.pm4 = pm4;
}
public String getPm5() {
if (pm5 == null && _row != null) {
pm5 = DataTableUtil.getStringValue(_row, "param5", null);
}
return pm5;
}
public void setPm5(String pm5) {
this.pm5 = pm5;
}
public String getPm6() {
if (pm6 == null && _row != null) {
pm6 = DataTableUtil.getStringValue(_row, "param6", null);
}
return pm6;
}
public void setPm6(String pm6) {
this.pm6 = pm6;
}
public String getPm7() {
if (pm7 == null && _row != null) {
pm7 = DataTableUtil.getStringValue(_row, "param7", null);
}
return pm7;
}
public void setPm7(String pm7) {
this.pm7 = pm7;
}
public String getPm8() {
if (pm8 == null && _row != null) {
pm8 = DataTableUtil.getStringValue(_row, "param8", null);
}
return pm8;
}
public void setPm8(String pm8) {
this.pm8 = pm8;
}
public String getPm9() {
if (pm9 == null && _row != null) {
pm9 = DataTableUtil.getStringValue(_row, "param9", null);
}
return pm9;
}
public void setPm9(String pm9) {
this.pm9 = pm9;
}
public String getPm10() {
if (pm10 == null && _row != null) {
pm10 = DataTableUtil.getStringValue(_row, "param10", null);
}
return pm10;
}
public void setPm10(String pm10) {
this.pm10 = pm10;
}
}
@@ -0,0 +1,489 @@
package org.example.Entity.Control.Com;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Base.RowComponent;
import org.example.Utils.DataTableUtil;
import org.example.Utils.IPublicUtil;
import org.example.Utils.NativeExtensionUtils;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
/**
* ==============================================================================
* 功能描述:SysPoPupMenu 右键菜单/单据工具表其他参数,
* 注意:其他参数中 以‘@’开头的,表示sql语句,以‘!’开头的表示存储过程,以#开头的表示多返回值得sql一般使用在拓展插件里面 所有以‘{}’包裹的,都要替换为对应的值
* 备注:actiontype :0表示存储过程 需要其他参数作为参数,一一对应,1表示sql 不需要其他参数,但需要替换对应行数据
* ==============================================================================
*/
public class SysPoPupMenuBtn extends Button {
public SysPoPupMenuBtn() {
super();
}
public SysPoPupMenuBtn(Map<String, Object> row) {
super(row);
this._row = row;
}
public SysPoPupMenuBtn(Map<String, Object> row, IPublicUtil util) {
super(row, util);
this._row = row;
this.setUtil(util);
}
@JsonIgnore
@Override
public String getXtype() {
return null;
}
@Override
public void setXtype(String xtype) {
super.setXtype(xtype);
}
@JsonIgnore
public int MenuBtnId;
@JsonIgnore
public String dllname;
private String __dllname;
public String get_dllname() {
if (dllname == null && getStoreName() != null && !getStoreName().isEmpty()) {
return getStoreName().toLowerCase();
}
if (__dllname == null) {
if (dllname == null) return "";
String[] names = dllname.toLowerCase().split("\\.");
__dllname = names.length > 1 ? names[1] : "";
if (names.length >= 3) {
String[] specialNames = {"tplbatchadd", "tpladd", "wordadd", "batchadd", "tableadd", "tabadd"};
for (String specialName : specialNames) {
if (specialName.equals(names[2]) || dllname.toLowerCase().contains(".machine")) {
__dllname = names[2];
break;
}
}
}
}
return __dllname;
}
public String action;
protected String getStoreName() {
if (actiontype == 1 && action != null && !action.trim().isEmpty()) {
return action.trim().split(" ")[0];
}
return "";
}
public int actiontype;
@JsonIgnore
public Map<String, Object> Record;
/// <summary>
/// 其他参数1
/// </summary>
@JsonIgnore
public String dllpar1;
/// <summary>
/// 其他参数2
/// </summary>
@JsonIgnore
public String dllpar2;
/// <summary>
/// 其他参数3
/// </summary>
@JsonIgnore
public String dllpar3;
/// <summary>
/// 其他参数4
/// </summary>
@JsonIgnore
public String dllpar4;
/// <summary>
/// 其他参数5
/// </summary>
@JsonIgnore
public String dllpar5;
/// <summary>
/// 其他参数6
/// </summary>
@JsonIgnore
public String dllpar6;
/// <summary>
/// 其他参数7
/// </summary>
@JsonIgnore
public String dllpar7;
/// <summary>
/// 其他参数8,单据为主表sql
/// </summary>
@JsonIgnore
public String dllpar8;
/// <summary>
/// 其他参数9,,单据为明细sql
/// </summary>
@JsonIgnore
public String dllpar9;
/// <summary>
/// 其他参数10,单据为单据编号
/// </summary>
@JsonIgnore
public String dllpar10;
@JsonIgnore
public String comfirm;
/// <summary>
/// 特殊参数是否选择人员或者步骤,用于提交或者审批
/// </summary>
@JsonIgnore
public String selectConfirmFlag;
/// <summary>
/// 特殊参数是否选择人员或者步骤,用于提交或者审批
/// </summary>
@JsonIgnore
public String nextSelectStepCode;
/// <summary>
/// 特殊参数是否选择人员或者步骤,用于提交或者审批
/// </summary>
@JsonIgnore
public String nextSelectStepOper;
/// <summary>
/// 转发需要人员
/// </summary>
@JsonIgnore
public String comfirmOpers;
/// <summary>
/// 转发备注
/// </summary>
@JsonIgnore
public String remark;
@JsonIgnore
public boolean maxWindow;
/// <summary>
/// 右键打开方式 0:窗口 1:tab,2:内嵌
/// </summary>
@JsonIgnore
public int showMode;
/// <summary>
/// 1:是否在表格上展示 2:在工具栏上显示(未实现)
/// </summary>
protected int toBar;
/// <summary>
/// 批量执行
/// </summary>
protected boolean multi;
private String _moduleId;
@JsonIgnore
// ModuleId属性
@JsonProperty("ModuleId")
public String getModuleId() {
switch (get_dllname()) {
case "pubadd":
case "pubadd2":
case "pubadd3":
case "tplbatchadd":
case "tpladd":
case "wordadd":
case "batchadd":
case "tableadd":
case "tabadd":
case "machine":
case "machine2":
case "machine3":
case "pubpagedetail":
case "pubbillinfo":
case "pubchart":
case "pubmoduletd":
default:
return NativeExtensionUtils.isNullOrEmpty(dllpar1) ? _moduleId : dllpar1;
case "pubmodule":
case "report":
case "baseinfo":
case "pubbill":
case "pubmoduledetailinfo":
case "pubmoduledetail":
return NativeExtensionUtils.isNullOrEmpty(dllpar2) ? dllpar1 : dllpar2;
case "photoview":
return dllpar4;
case "pubattachment":
return dllpar3;
case "pubaccraditation":
case "baseaccraditation":
return dllpar2;
}
}
public void setModuleId(String moduleId) {
this._moduleId = moduleId;
}
private int _serverId;
@JsonIgnore
@JsonProperty("ServerId")
public int getServerId() {
switch (get_dllname()) {
case "pubadd":
case "pubadd2":
case "pubadd3":
case "tplbatchadd":
case "tpladd":
case "wordadd":
case "batchadd":
case "tableadd":
case "machine":
case "machine2":
case "machine3":
case "pubpagedetail":
case "pubbillinfo":
case "pubchart":
case "pubmoduletd":
return DataTableUtil.getIntValue(dllpar7, 0);
case "pubmodule":
case "report":
case "baseinfo":
case "pubbill":
case "pubmoduledetailinfo":
case "pubmoduledetail":
return DataTableUtil.getIntValue(dllpar3, 0);
case "pubaccraditation":
case "baseaccraditation":
return DataTableUtil.getIntValue(dllpar1, 0);
default:
return 0;
}
}
public void setServerId(int serverId) {
this._serverId = serverId;
}
@JsonProperty("Updateable")
protected boolean isUpdateable() {
switch (get_dllname()) {
case "pubadd":
case "pubadd2":
case "pubadd3":
case "tplbatchadd":
case "tpladd":
case "wordadd":
case "batchadd":
case "tableadd":
case "tabadd":
case "machine":
case "machine2":
case "machine3":
case "photoview":
return !DataTableUtil.getBooleanValue(dllpar2, false);
case "baseinfo":
return !DataTableUtil.getBooleanValue(dllpar1, false);
default:
return true;
}
}
@JsonIgnore
// IdValue属性
@JsonProperty("IdValue")
public String getIdValue() {
switch (get_dllname()) {
case "pubadd":
case "pubadd2":
case "pubadd3":
case "tplbatchadd":
case "tpladd":
case "wordadd":
case "batchadd":
case "tableadd":
case "tabadd":
case "machine":
case "machine2":
case "machine3":
return dllpar3;
case "pubbillinfo":
return dllpar2;
case "pubbill":
return dllpar10;
case "photoview":
return dllpar1;
case "windowwordcard":
case "windowcard":
case "windowcuscard":
case "pubaccraditation":
case "baseaccraditation":
return dllpar4;
case "baseinfo":
return dllpar3;
default:
return dllpar2;
}
}
@JsonIgnore
// UnionCond属性
@JsonProperty("UnionCond")
public String getUnionCond() {
switch (get_dllname()) {
case "pubpagedetail":
case "pubmodule":
case "pubmoduledetailinfo":
return dllpar7;
default:
return "";
}
}
@JsonIgnore
// UnionValue属性
@JsonProperty("UnionValue")
public String getUnionValue() {
switch (get_dllname()) {
case "pubpagedetail":
return dllpar2;
case "pubbillinfo":
return dllpar2;
case "photoview":
case "pubattachment":
return dllpar1;
case "baseinfo":
return dllpar3;
case "pubmodule":
case "pubadd":
case "pubadd2":
case "pubadd3":
case "tplbatchadd":
case "tpladd":
case "wordadd":
case "batchadd":
case "tableadd":
case "tabadd":
case "pubmoduledetailinfo":
return dllpar5;
default:
return "";
}
}
@JsonIgnore
// UnionField属性
@JsonProperty("UnionField")
public String getUnionField() {
switch (get_dllname()) {
case "pubmodule":
case "pubadd":
case "pubadd2":
case "pubadd3":
case "tplbatchadd":
case "tpladd":
case "wordadd":
case "batchadd":
case "tableadd":
case "tabadd":
case "pubmoduledetailinfo":
return dllpar4;
default:
return "";
}
}
@JsonIgnore
// PmStr属性
@JsonProperty("PmStr")
public String getPmStr() {
if ("pubmoduledetailinfo".equals(get_dllname())) {
return dllpar3;
}
if ("tplbatchadd".equals(get_dllname())) return dllpar6;
if (getIdValue() != null && !getIdValue().isEmpty()) return "";
return dllpar6;
}
// Pms属性
@JsonIgnore
@JsonProperty("Pms")
public Map<String, Object> Pms;
// PmOffset属性
@JsonProperty("PmOffset")
public int getPmOffset() {
if (get_dllname() == null || get_dllname().isEmpty()) return 0;
switch (get_dllname()) {
case "report":
return 3;
case "pubbill":
return 2;
default:
return 3;
}
}
private Map<String, Object> _popPms;
@JsonIgnore
// PopPms属性
@JsonProperty("PopPms")
public Map<String, Object> getPopPms() {
if (_popPms != null) return _popPms;
Map<String, Object> _retTab = new HashMap<>();
if (Pms != null) {
_retTab.putAll(Pms);
}
_retTab.put("p_1", dllpar1);
_retTab.put("p_2", dllpar2);
_retTab.put("p_3", dllpar3);
_retTab.put("p_4", dllpar4);
_retTab.put("p_5", dllpar5);
_retTab.put("p_6", dllpar6);
_retTab.put("p_7", dllpar7);
_retTab.put("p_8", dllpar8);
_retTab.put("p_9", dllpar9);
_retTab.put("p_10", dllpar10);
Map<String, Object> retTab = new HashMap<>();
for (Map.Entry<String, Object> entry : _retTab.entrySet()) {
if (entry.getValue() != null && !entry.getValue().toString().isEmpty()) {
try {
int i = Integer.parseInt(entry.getKey().substring(2));
if (i == 6) {
switch (get_dllname()) {
case "pubadd":
case "pubadd2":
case "pubadd3":
case "tplbatchadd":
case "tpladd":
break;
default:
retTab.put("p_" + (i - getPmOffset()), entry.getValue());
break;
}
} else {
retTab.put("p_" + (i - getPmOffset()), entry.getValue());
}
} catch (NumberFormatException e) {
// 忽略非数字键
}
}
}
_popPms = retTab;
return retTab;
}
}
@@ -0,0 +1,54 @@
package org.example.Entity.Control.Container;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Panel.Panel;
import org.example.Utils.MD5Util;
/**
* ==============================================================================
* 功能描述:ChartContainer
* ==============================================================================
*/
public class ChartContainer extends Panel {
public ChartContainer() {
super();
this.defaultXtype = "plugins.PubChart.ChartFormater";
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public String ModuleId;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String DetailId;
private String _s;
private String _ens;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getS() {
if (_ens == null && _s != null && !_s.isEmpty()) {
_ens = MD5Util.encrypt(_s);
}
return _ens;
}
public void setS(String value) {
_s = value;
_ens = null;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object ChartCfg;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object RightMenu;
public Integer displayRows;
}
@@ -0,0 +1,26 @@
package org.example.Entity.Control.Container;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Fields.Field;
public class Column extends Field {
public Column() {
super(null);
this.defaultXtype = "gridcolumn";
}
/**
* 标题
*/
public String text;
/**
* 指向的数据名称
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public String dataIndex;
}
@@ -0,0 +1,42 @@
package org.example.Entity.Control.Container;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Fields.Field;
import org.example.Utils.DataTableUtil;
import org.example.Utils.IPublicUtil;
import java.util.Map;
public class FieldSet extends Field {
public FieldSet(Map<String, Object> row) {
super(row);
this.defaultXtype = "fieldset";
}
public FieldSet(Map<String, Object> row, IPublicUtil util) {
super(row, util);
this.defaultXtype = "fieldset";
}
/**
* 标题,从FieldCaption或GroupName字段获取
*/
public String getTitle() {
Object value = DataTableUtil.get(_row, new String[]{"FieldCaption", "GroupName"}, "");
return value != null ? value.toString() : "";
}
/**
* 是否折叠,基于isexpand字段判断
*/
public boolean isCollapsed() {
Object value = _row.getOrDefault("isexpand", "1");
if (value == null) return false;
if (value instanceof Boolean) return !(Boolean) value;
String strValue = (String) value;
return !("1".equals(strValue) || "true".equalsIgnoreCase(strValue));
}
}
@@ -0,0 +1,27 @@
package org.example.Entity.Control.Container;
import org.example.Entity.Control.Fields.Field;
import java.util.Map;
public class Image extends Field {
public Image(Map<String, Object> row) {
super(row);
this.defaultXtype = "img";
}
private String _src;
public String getSrc() {
if (_src == null || _src.isEmpty()) {
_src = getDefaultval() != null ? getDefaultval() + "" : "";
}
return _src;
}
public void setSrc(String src) {
this._src = src;
}
}
@@ -0,0 +1,46 @@
package org.example.Entity.Control.Container;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.example.Entity.Control.Base.Component;
import java.util.Objects;
/**
* ==============================================================================
* 功能描述:MContainer 容器,xtype 由 dllname 和 dlltype 决定,用于多标签打开的模块
* ==============================================================================
*/
public class MContainer extends Component {
public MContainer() {
super();
this.defaultXtype = "MContainer";
}
public String mXtype;
public String title;
public String ModuleId;
public String ParentModuleId;
public String DetailId;
public Object store;
private String _leftUnionName;
public String getLeftUnionName() {
return Objects.toString(_leftUnionName, "").toLowerCase().replace("{", "").replace("}", "");
}
public void setLeftUnionName(String leftUnionName) {
this._leftUnionName = leftUnionName;
}
public String leftUnionValueName;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object MobileCards;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object QueryPms;
public Object ElseValue;
}
@@ -0,0 +1,423 @@
package org.example.Entity.Control.Container;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Fields.ComboBox;
import org.example.Entity.Control.Fields.Field;
import org.example.Entity.Control.Validators.VBase;
import org.example.Entity.System.ModuleEntity;
import org.example.Enums.SystemEnums;
import org.example.Utils.DataTableUtil;
import org.example.Utils.IPublicUtil;
import org.example.Utils.NativeExtensionUtils;
import org.example.Utils.PublicUtil;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import static org.example.Utils.NativeExtensionUtils.*;
// 假设 Field 类是 RowColumn 的父类
public class RowColumn extends Field {
public RowColumn(Map<String, Object> _row, boolean selfEdit) {
super(_row);
this.selfEdit = selfEdit;
}
public RowColumn(Map<String, Object> _row, boolean selfEdit, IPublicUtil util) {
super(_row, util);
this.selfEdit = selfEdit;
}
private String _xtype;
@Override
public String getXtype() {
if (_xtype == null || _xtype.isEmpty()) {
_xtype = PublicUtil.GetEColumnTypeByCType(getFdType());
if (getEditor() != null && !isValeqkey()) {
_xtype = "editor.editColumn";
if (getDataSource() == null || getDataSource().isEmpty()) {
_xtype = "gridcolumn";
}
} else if (!isEditable() && getUneditor() != null) {
_xtype = "editor.comboboxColumn";
if (getDataSource() == null || getDataSource().isEmpty()) {
_xtype = "gridcolumn";
}
} else if ("gridcolumn".equals(_xtype) && getFieldDbType() > 0) {
_xtype = PublicUtil.TypeToColumnType(PublicUtil.SqlxtypeToProType(getFieldDbType()));
}
if (getEditor() != null && isValeqkey()) {
setFormat("");
}
}
return _xtype;
}
@Override
public void setXtype(String xtype) {
this._xtype = xtype;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("Linknames")
public String[] linknames;
private Boolean _locked;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("Locked")
public Boolean getLocked() {
if (_locked == null) {
_locked = DataTableUtil.getBooleanValue(_row, "locked", false);
}
return _locked ? _locked : null;
}
public void setLocked(Boolean locked) {
this._locked = locked;
}
private Boolean _scanAble;
@JsonIgnore
public Boolean getScanAble() {
if (_scanAble == null) {
_scanAble = DataTableUtil.getBooleanValue(_row, "scanAble", false);
}
return _scanAble ? _scanAble : null;
}
public void setScanAble(Boolean scanAble) {
this._scanAble = scanAble;
}
private Object _scanField;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ScanField")
public Object getScanField() {
if (getScanAble() != null && getScanAble()) {
_scanField = getUtil().createControl(_row, module, false);
}
return _scanField;
}
@JsonIgnore
public ModuleEntity module;
public Integer width;
@Override
public Integer getWidth() {
return ToInt32(DataTableUtil.getIntValue(_row, "width", 100));
}
public Integer height;
@Override
public Integer getHeight() {
return null;
}
@Override
public Boolean getHidden() {
return super.getColHidden();
}
public Boolean getAutoRowspan() {
Boolean _r = DataTableUtil.getBooleanValue(_row, "rowspan", false);
return _r ? _r : null;
}
public int ControlTabIndex;
private SystemEnums.ControlType _FieldType;
@JsonIgnore
public SystemEnums.ControlType getFdType() {
if (_FieldType == null) {
try {
Object obj = Enum.valueOf(SystemEnums.ControlType.class, String.valueOf(getFieldType()));
if (obj != null) {
_FieldType = (SystemEnums.ControlType) obj;
}
} catch (IllegalArgumentException e) {
_FieldType = SystemEnums.ControlType.LabText;
}
}
if (PublicUtil.SqlxtypeToProType(getFieldDbType()) == Boolean.class) {
_FieldType = SystemEnums.ControlType.LabCheckBox;
} else if (isIsSum() && (getFormat() == null || getFormat().toLowerCase().indexOf("yy") < 0)) {
_FieldType = SystemEnums.ControlType.LabTextInt;
}
return _FieldType != null ? _FieldType : SystemEnums.ControlType.LabText;
}
@JsonIgnore
public int getFieldDbType() {
String val = DataTableUtil.getStringValue(_row, new String[]{"FieldDbType"}, "");
return ToInt32(val);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("DataType")
public String getDataType() {
String datatype = DataTableUtil.getStringValue(_row, new String[]{"datatype"}, "");
switch (datatype.toLowerCase()) {
case "varchar":
return "textfield";
case "datetime":
return "datefield";
default:
return "";
}
}
public Boolean getDisabled() {
return null;
}
@JsonIgnore
public String getFieldName() {
return ((String) DataTableUtil.getRowVal(_row, new String[]{"fieldname"}, "")).toLowerCase();
}
public String getDataIndex() {
return getFieldName();
}
@JsonIgnore
@Override
public Integer getLeft() {
return super.getLeft();
}
@JsonIgnore
@Override
public void setLeft(Integer left) {
super.setLeft(left);
}
@JsonIgnore
@Override
public Integer getTop() {
return super.getTop();
}
@JsonIgnore
@Override
public void setTop(Integer top) {
super.setTop(top);
}
public String getText() {
String label = getFieldLabel();
return (label == null || label.isEmpty()) ? getDataIndex() : label;
}
public Integer getTextAlign() {
int textAlign = ToInt32(DataTableUtil.get(_row, "TextAlign", getFieldLabel(), 0));
return textAlign != 0 ? textAlign : null;
}
private String _fieldLabel;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("FieldLabel")
public String getFieldLabel() {
String label = (String) DataTableUtil.get(_row, "FieldCaption", _fieldLabel, "");
if (label != null && !label.isEmpty()) {
label = label.replace("\r\n", "");
if (label.indexOf("|") > -1) {
String[] ls = label.split("\\|");
return ls[1];
}
}
return label;
}
public void setFieldLabel(String fieldLabel) {
this._fieldLabel = fieldLabel;
}
private Boolean selfEdit;
private Boolean _editable;
public boolean isEditable() {
if (_editable != null) {
return _editable;
}
_editable = !super.isReadOnly() && selfEdit;
return _editable;
}
public void setEditable(boolean editable) {
this._editable = editable;
if (getEditor() != null && getEditor() instanceof Field) {
((Field) getEditor()).setReadOnly(false);
}
}
private Object _uneditor;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object getUneditor() {
if (_uneditor == null) {
Object _tmp = getEditor();
}
return _uneditor;
}
public void setUneditor(Object uneditor) {
this._uneditor = uneditor;
}
private Object _editor;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object getEditor() {
Boolean resultdisabled = getDisabled() != null ? getDisabled() : false;
if (getFdType() != SystemEnums.ControlType.LabCheckBox && _editor == null && !resultdisabled) {
boolean[] valeqkeyHolder = new boolean[1];
_editor = getUtil().getGridColumnEditType(this, _row, module, valeqkeyHolder);
this._valekey = valeqkeyHolder[0];
if (!valeqkeyHolder[0] && _editor != null && _editor instanceof ComboBox) {
_uneditor = _editor;
}
}
if (!isEditable()) {
return null;
}
_uneditor = null;
return _editor;
}
public String tdCls;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("TdCls")
public String getTdCls() {
return isEditable() ? "editable" : null;
}
private Boolean _valekey = null;
public Boolean isValeqkey() {
if (_valekey == null && getEditor() == null) {
_valekey = true;
}
return (_valekey != null) ? _valekey : true;
}
public void setValeqkey(Boolean valeqkey) {
this._valekey = valeqkey;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("TagId")
public Integer getTagId() {
int _tagId = DataTableUtil.getIntValue(_row, "tagid", 0);
return _tagId > 0 ? _tagId : null;
}
private Object _fDefaultVal;
@JsonProperty("fDefaultVal")
public Object getFDefaultVal() {
if (_fDefaultVal == null) {
_fDefaultVal = DataTableUtil.getRowVal(_row, "defaultValue", null);
if (_fDefaultVal != null && _fDefaultVal.toString().startsWith("@")) {
_fDefaultVal = "";
}
}
return _fDefaultVal;
}
@JsonProperty("StoreFieldType")
public String getStoreFieldType() {
return PublicUtil.GetEFieldTypeByCType(getFdType(), getFormat());
}
@JsonIgnore
public Object getStoreField() {
Object DefaultValue = getDefaultval();
if (DefaultValue == null || DefaultValue.toString().isEmpty()) {
DefaultValue = PublicUtil.GetDefaultValByCType(getFdType());
}
Object Validators = null;
if (!isAllowBlank()) {
Validators = new VBase[]{new VBase("Presence")};
}
Object finalDefaultValue = DefaultValue;
Object finalValidators = Validators;
return new Object() {
public final String text = getText();
public final String name = getDataIndex();
public final String type = getStoreFieldType();
public final Object defaultValue = finalDefaultValue;
public final String dateFormat = getFormat();
public final Object validators = finalValidators;
};
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("BandTitle")
public String getBandTitle() {
String label = DataTableUtil.getStringValue(_row, "FieldCaption", _fieldLabel);
if (label != null && !label.isEmpty() && label.indexOf("|") > -1) {
String[] ls = label.split("\\|");
return ls[0];
}
return DataTableUtil.getStringValue(_row, "bandtitle", "");
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("BandFields")
public String[] getBandFields() {
if (!isNullOrEmpty(getBandTitle())) {
if (isNullOrEmpty(DataTableUtil.getStringValue(_row, "bandtitle", ""))) {
return new String[]{getDataIndex()};
}
String fields = (String) DataTableUtil.getStringValue(_row, "bandfield", null);
if (!isNullOrEmpty(fields)) {
String[] result = Arrays.stream(fields.toLowerCase().split("[|,]"))
.filter(str -> str != null && !str.trim().isEmpty())
.toArray(String[]::new);
return result;
}
return null;
}
return null;
}
}
@@ -0,0 +1,77 @@
package org.example.Entity.Control.Data;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Base.Base;
import java.util.Objects;
/**
* ==============================================================================
* 功能描述:DataStore
* ==============================================================================
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class DataStore extends Base {
public DataStore() {
super();
this.defaultXtype = "datastore";
}
/**
* 此参数可以用来代替model参数. fields值应该是一个Ext.data.Field属性对象的集合
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public String url;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean getIsApi() {
if (url != null && !url.isEmpty()) {
return true;
}
return null;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object getApi() {
if ((ApiDataNode != null && !ApiDataNode.isEmpty()) || (ApiSuccNode != null && !ApiSuccNode.isEmpty()) || (ApiSuccVal != null && !ApiSuccVal.isEmpty())) {
return new Object() {
public final Object reader = new Object() {
public final String success = ApiSuccNode;
public final String data = ApiDataNode;
public final String successVal = ApiSuccVal;
};
};
}
return null;
}
@JsonIgnore
public String ApiDataNode;
@JsonIgnore
public String ApiSuccNode;
@JsonIgnore
public String ApiSuccVal;
/**
* 此参数可以用来代替model参数. fields值应该是一个Ext.data.Field属性对象的集合
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object[] fields;
/**
* 数据
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object data;
/**
* 存在的参数
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object extraParams;
}
@@ -0,0 +1,35 @@
package org.example.Entity.Control.Fields;
import org.example.Entity.Control.Fields.Field;
import org.example.Utils.DataTableUtil;
import java.util.Map;
/**
* ==============================================================================
* 功能描述:Checkbox 组件
* ==============================================================================
*/
public class Checkbox extends Field {
public Checkbox(Map<String, Object> row) {
super(row);
this.defaultXtype = "checkbox";
}
private Boolean _value;
@Override
public Object getValue() {
if (_value == null) {
return DataTableUtil.toBoolean(getDefaultval(), false);
}
return _value;
}
@Override
public void setValue(Object value) {
this._value = DataTableUtil.toBoolean(value, false);
}
}
@@ -0,0 +1,302 @@
package org.example.Entity.Control.Fields;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Fields.Field;
import org.example.Entity.Control.Container.Column;
import org.example.Enums.SystemTypeEnums;
import org.example.Utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Component;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.example.Utils.DataTableUtil.get;
/**
* ==============================================================================
* 功能描述:ComboBox
* ==============================================================================
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ComboBox extends Field {
public static final Pattern RECORD_PATTERN_1 = Pattern.compile("#([^#])+#");
public static final Pattern RECORD_PATTERN_2 = Pattern.compile("\\{([^{])+}");
public ComboBox(Map<String, Object> row) {
super(row);
this.defaultXtype = "combobox";
}
public ComboBox(Map<String, Object> row, IPublicUtil util) {
this(row);
this.setUtil(util);
}
/**
* 联动,触发该控件刷新的上级控件名称
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public String[] getLinkParentNames() {
if (!isIsPostRecord()) {
return null;
}
String[] names = PublicUtil.getParamValue(getDataSource())
.stream()
.map(str -> str.replaceAll("[{}]", "").toLowerCase())
.toArray(String[]::new);
if (names.length == 0) {
return null;
}
return names;
}
/**
* 是否是带参数的下拉框
*/
@JsonIgnore
public boolean parmbox;
/**
* 是否可输入
*/
public boolean editable;
/**
* 是否可以多选
*/
public boolean multiSelect;
/**
* 查询的参数名
*/
public String queryParam;
/**
* 查询时,是否需要把自身的recordpost到服务器
*/
public boolean isIsPostRecord() {
String dataSource = getDataSource();
if (dataSource == null || dataSource.isEmpty()) {
return false;
}
Matcher matcher1 = RECORD_PATTERN_1.matcher(dataSource);
Matcher matcher2 = RECORD_PATTERN_2.matcher(dataSource);
return matcher1.find() || matcher2.find();
}
public String emptyText;
private boolean autoSelect = true;
public boolean isAutoSelect() {
return autoSelect;
}
public void setAutoSelect(boolean autoSelect) {
this.autoSelect = autoSelect;
}
/**
* 其他字段 格式:字段|显示名称,字段2|显示名称
*/
private List<Column> _otherMember;
@JsonInclude(JsonInclude.Include.NON_NULL)
public List<Column> getColumns() {
if (_otherMember == null) {
List<Column> list = new ArrayList<>();
String omembers = (String) get(_row, "OtherMember", null);
// 处理OtherMember配置的列
if (omembers != null && !omembers.trim().isEmpty()) {
String[] ms = omembers.split(",");
for (String m : ms) {
if (m == null || m.trim().isEmpty()) {
continue;
}
String[] kv = (m + "|").split("\\|");
Column column = new Column();
column.text = kv.length > 1 ? kv[1].trim() : ""; // 处理没有|分隔的情况
column.dataIndex = kv[0].trim();
column.setWidth(1);
list.add(column);
}
if (!list.isEmpty()) {
_otherMember = list;
} else {
return null; // 对应C#的 list.Count == 0 逻辑
}
}
// 处理数据源SQL获取的列
else if (getDataSource() != null && !getDataSource().isEmpty() && !isReadOnly()) {
String sql = getDataSource();
List<Map<String, Object>> tbVal = null;
Set<String> columnNames = new HashSet<>();
try {
// 处理SQL:移除#符号并添加and 1!=1条件
String processedSql = sql.replace("#", "");
SqlAnalyzer sqlAnalyzer = new SqlAnalyzer(processedSql);
Map<String, String> paramMap = new HashMap<>();
paramMap.put("a", "and 1!=1");
sql = sqlAnalyzer.InsertWhere(paramMap, false, false, false);
// 执行查询并收集列名(通过ResultSetMetaData
this.getDbOperator().query(
PublicUtil.ReqSqlPmsByRow(null, null, sql, SystemTypeEnums.PmType.sql),
new ResultSetExtractor<Void>() {
@Override
public Void extractData(ResultSet rs) throws SQLException, DataAccessException {
// 无论是否有行数据,先获取元数据
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
columnNames.add(metaData.getColumnName(i));
}
// 如需处理行数据,再循环 rs.next()
return null;
}
}
);
} catch (Exception e) {
// err.printf("解析下拉框列时执行sql错误:SQL=%s, 错误信息=%s%n", sql, e.getMessage());
}
// 处理列过滤和转换
if (!columnNames.isEmpty()) {
List<Column> otherMemberList = new ArrayList<>();
String valueMember = DataTableUtil.getStringValue(_row, "ValueMember", "");
String displayField = getDisplayField();
String valueField = getValueField();
String xtype = getXtype() != null ? getXtype().toLowerCase() : "";
for (String colName : columnNames) {
// 过滤条件:wincombobox类型或非特殊列,且列名不以_开头
boolean isWinComboBox = "wincombobox".equals(xtype);
boolean isNotSpecialColumn = !colName.equals(displayField)
&& !colName.equals(valueField)
&& !colName.equals(valueMember);
boolean condition = (isWinComboBox || isNotSpecialColumn)
&& !colName.startsWith("_");
if (condition) {
Column column = new Column();
// 设置列文本(对应C#的三元表达式逻辑)
if ("dm".equals(colName)) {
column.text = "编码";
} else if ("mc".equals(colName)) {
column.text = "名称";
} else if ("remark".equals(colName)) {
column.text = "备注";
} else {
column.text = colName;
}
// 设置数据索引和宽度
column.dataIndex = colName;
column.setWidth(getColumnWidth(colName));
otherMemberList.add(column);
}
}
// 空列集合处理
if (otherMemberList.isEmpty()) {
_otherMember = null;
} else {
_otherMember = otherMemberList;
}
// 单列或可编辑状态下添加显示列和值列
if ((_otherMember != null && _otherMember.size() == 1) || this.editable) {
if (_otherMember == null) {
_otherMember = new ArrayList<>();
}
// 添加显示列(名称)
if (displayField != null && !displayField.startsWith("_")) {
Column displayColumn = new Column();
displayColumn.text = "名称";
displayColumn.dataIndex = displayField;
displayColumn.setWidth(1);
_otherMember.add(0, displayColumn);
}
// 添加值列(编号)
if (displayField != null && valueField != null
&& !displayField.equals(valueField)
&& !valueField.startsWith("_")) {
Column valueColumn = new Column();
valueColumn.text = "编号";
valueColumn.dataIndex = valueField;
valueColumn.setWidth(1);
_otherMember.add(0, valueColumn);
}
}
}
}
}
return _otherMember;
}
public void setColumns(List<Column> columns) {
this._otherMember = columns;
}
public String getColumnText(String colName) {
switch (colName) {
case "dm":
return "编码";
case "mc":
return "名称";
case "remark":
return "备注";
default:
return colName;
}
}
private int getColumnWidth(String colName) {
if ("dm".equals(colName) || "编码".equals(colName)) {
return 1;
} else if ("mc".equals(colName) || "名称".equals(colName)
|| "remark".equals(colName) || "备注".equals(colName)) {
return 2;
} else {
return 2;
}
}
/**
* 下拉框的类型
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public String pickxtype;
/**
* 下拉框的类型
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object pickerCfg;
/**
* 是否在获取值的时候,获取匹配的下拉值
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean MValue;
@JsonIgnore
public boolean isDoNotSpelling() {
return NativeExtensionUtils.toBoolean(DataTableUtil.getIntValue(_row, "donotspelling", 0));
}
}
@@ -0,0 +1,10 @@
package org.example.Entity.Control.Fields;
import java.util.Map;
public class ComboTreeBox extends ComboBox {
public ComboTreeBox(Map<String, Object> row) {
super(row);
}
}
@@ -0,0 +1,98 @@
package org.example.Entity.Control.Fields;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
// 假设这里存在 Field 类
import org.example.Entity.Control.Fields.Field;
import org.example.Utils.NativeExtensionUtils;
import java.util.regex.Pattern;
public class DateField extends Field {
private String _format;
public DateField(java.util.Map<String, Object> row) {
super(row);
this.defaultXtype = "fields.Date";
}
public String getFormat() {
if (_format == null || _format.isEmpty()) {
return "yyyy-MM-dd";
}
return _format.replace("DD", "dd");
}
public void setFormat(String format) {
this._format = format;
}
@Override
public Object getValue() {
String formater = this.getFormat(); // 对应 C# 的 this.format
Date outdate;
// 处理 defaultsource 以 "{#p_" 开头且 defaultval 为空的情况
if (getDefaultsource() != null && getDefaultsource().startsWith("{#p_")
&& (getDefaultval() == null || (getDefaultval() + "").trim().isEmpty())) {
return getDefaultsource();
}
// 处理两者均为空的情况
if ((getDefaultsource() == null || getDefaultsource().trim().isEmpty())
&& (getDefaultval() == null || (getDefaultval() + "").trim().isEmpty())) {
return null;
}
// 解析 defaultval 为日期,失败则使用当前时间
outdate = NativeExtensionUtils.toDateTime(getDefaultval());
if (outdate == null) { // 若工具类返回 null,兜底为当前时间
outdate = new Date();
}
// 按格式返回字符串(使用 SimpleDateFormat
if (formater == null || formater.isEmpty()) {
formater = "yyyy-MM-dd"; // 默认格式,可参考 DateField 类
}
try {
SimpleDateFormat sdf = new SimpleDateFormat(formater);
return sdf.format(outdate);
} catch (IllegalArgumentException e) {
// 处理非法格式,返回默认格式
return new SimpleDateFormat("yyyy-MM-dd").format(outdate);
}
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object getMin() {
return getLimitMinValue();
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object getMax() {
if (NativeExtensionUtils.isNullOrEmpty(getLimitMaxValue())) {
return null;
}
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.parse(getLimitMaxValue() + "");
return getLimitMaxValue();
} catch (ParseException e) {
return null;
}
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object getDateType() {
String formatStr = getFormat().toLowerCase();
return formatStr.contains("hh") ? "datetime" : null;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,16 @@
package org.example.Entity.Control.Fields;
import java.util.Map;
// 假设这里存在 Field 类
import org.example.Entity.Control.Fields.Field;
public class FileButton extends Field {
public String text;
public FileButton(Map<String, Object> row) {
super(row);
this.setXtype("filebutton");
}
}
@@ -0,0 +1,12 @@
package org.example.Entity.Control.Fields;
import java.util.Map;
public class Hidden extends Field {
public Hidden(Map<String, Object> row) {
super(row);
setXtype("hidden");
}
}
@@ -0,0 +1,24 @@
package org.example.Entity.Control.Fields;
import java.util.Map;
import java.util.Objects;
// 假设存在一个工具类用于类型转换
import org.example.Utils.NativeExtensionUtils;
public class ImageFiled extends Field {
public boolean uFolder = true;
public ImageFiled(Map<String, Object> row) {
super(row);
this.defaultXtype = "field.imgupload";
}
public int getFNums() {
Object limitMaxValue = getLimitMaxValue();
String limitMaxValueStr = Objects.toString(limitMaxValue, "1");
return NativeExtensionUtils.parseInt(limitMaxValueStr);
}
}
@@ -0,0 +1,68 @@
package org.example.Entity.Control.Fields;
import org.example.Entity.Control.Base.Component;
import org.example.Utils.NativeExtensionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class LabelCheckBox extends Field {
private Field mainfield;
public boolean hideLabel = true;
public LabelCheckBox(Map<String, Object> row, Field field) {
super(row);
this.defaultXtype = "CheckFieldContainer";
this.mainfield = field;
}
@Override
public Object getDefaultval() {
return super.getDefaultval();
}
@Override
public void setDefaultval(Object value) {
super.setDefaultval(value);
String valueStr = value != null ? value.toString() : "";
boolean empty = valueStr.isEmpty();
((Checkbox) getItems().get(0)).setValue(!empty);
Field subField = (Field) getItems().get(1);
subField.setDefaultval(valueStr);
subField.disabled = (empty);
}
@Override
public void setTabIndex(Integer value) {
((Field) getItems().get(1)).setTabIndex(value);
}
private List<Component> _items;
public List<Component> getItems() {
if (_items == null) {
_items = new ArrayList<>();
this.mainfield.setTop(0);
this.mainfield.setLeft(18);
if (this.getWidth() != null) {
this.mainfield.setWidth(this.getWidth() - 18);
}
Checkbox cbox = new Checkbox(null);
cbox.setName(this.getName() + "_ckbox");
cbox.setXtype("labelCheckBox");
String mainFieldDefaultVal = this.mainfield.getDefaultval() != null ? this.mainfield.getDefaultval().toString() : "";
String mainFieldValue = this.mainfield.getValue() != null ? this.mainfield.getValue().toString() : "";
boolean hasValue = !mainFieldDefaultVal.isEmpty() || !mainFieldValue.isEmpty();
cbox.setValue(hasValue);
cbox.setTop(3);
this.mainfield.disabled = (!NativeExtensionUtils.toBoolean(cbox.getValue(), false));
_items.add(cbox);
_items.add(this.mainfield);
}
return _items;
}
}
@@ -0,0 +1,17 @@
package org.example.Entity.Control.Fields;
import java.util.Map;
public class LabelField extends Field {
public LabelField(Map<String, Object> row) {
super(row);
this.setXtype("label");
}
public String getText() {
return getFieldLabel();
}
}
@@ -0,0 +1,115 @@
package org.example.Entity.Control.Fields;
import org.example.Entity.Control.Base.Component;
import org.example.Entity.Control.Com.Button;
import org.example.Utils.DataTableUtil;
import org.example.Utils.IPublicUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class MapLocationField extends Field {
private String icon;
private String glyph;
public MapLocationField(Map<String, Object> row) {
super(row);
this.defaultXtype = "maplocationfield";
}
public MapLocationField(Map<String, Object> row, IPublicUtil util) {
super(row, util);
this.defaultXtype = "maplocationfield";
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getGlyph() {
return glyph;
}
public void setGlyph(String glyph) {
this.glyph = glyph;
}
@Override
public void setTabIndex(Integer value) {
if (getItems() != null && !getItems().isEmpty()) {
((TextField) getItems().get(0)).setTabIndex(value);
}
}
private List<Component> _items;
public List<Component> getItems() {
if (_items == null) {
_items = new ArrayList<>();
TextField text = new TextField(this._row);
text.setTop(0);
text.setLeft(0);
if (this.getWidth() != null) {
text.setWidth(this.getWidth() - 30);
}
Button img = new Button();
img.width = (25);
img.setTop(1);
img.height = (text.getHeight());
if (text.getWidth() != null) {
img.setLeft(text.getWidth() + 1);
}
img.setHandler("OpenLocationMap");
Hidden longitude = new Hidden(null);
longitude.setName(this.getName() + "_longitude");
Hidden latitude = new Hidden(null);
latitude.setName(this.getName() + "_latitude");
Hidden itude = new Hidden(null);
itude.setName(this.getName() + "_itude");
Hidden province = new Hidden(null);
province.setName(this.getName() + "_province");
Hidden city = new Hidden(null);
city.setName(this.getName() + "_city");
Hidden district = new Hidden(null);
district.setName(this.getName() + "_district");
Hidden street = new Hidden(null);
street.setName(this.getName() + "_street");
_items.add(text);
_items.add(img);
_items.add(longitude);
_items.add(latitude);
_items.add(itude);
_items.add(province);
_items.add(city);
_items.add(district);
_items.add(street);
}
return _items;
}
@Override
public void setDefaultVal(Map<String, Object> updrow) {
if (getItems() != null && !getItems().isEmpty()) {
((TextField) getItems().get(0)).setDefaultval(DataTableUtil.getRowVal(updrow, this.getName(), ""));
((Hidden) getItems().get(2)).setDefaultval(DataTableUtil.getRowVal(updrow, this.getName() + "_longitude", ""));
((Hidden) getItems().get(3)).setDefaultval(DataTableUtil.getRowVal(updrow, this.getName() + "_latitude", ""));
((Hidden) getItems().get(4)).setDefaultval(DataTableUtil.getRowVal(updrow, this.getName() + "_itude", ""));
}
}
}
@@ -0,0 +1,16 @@
package org.example.Entity.Control.Fields;
import org.example.Utils.IPublicUtil;
import java.util.Map;
public class NumberField extends TextField {
public NumberField(Map<String, Object> row) {
super(row);
this.defaultXtype = "numberfield";
}
}
@@ -0,0 +1,80 @@
package org.example.Entity.Control.Fields;
import org.example.Entity.Control.Base.Component;
import org.example.Entity.Control.Com.Button;
import org.example.Utils.DataTableUtil;
import org.example.Utils.IPublicUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class TextAreaEditor extends Field {
public String icon;
public String glyph;
public TextAreaEditor(Map<String, Object> row) {
super(row);
this.setXtype("fields.textareaeditor");
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getGlyph() {
return glyph;
}
public void setGlyph(String glyph) {
this.glyph = glyph;
}
@Override
public void setTabIndex(Integer value) {
if (getItems() != null && !getItems().isEmpty()) {
((TextField) getItems().get(0)).setTabIndex(value);
}
}
private List<Component> _items;
public List<Component> getItems() {
if (_items == null) {
_items = new ArrayList<>();
TextField text = new TextField(this._row);
text.setTop(0);
text.setLeft(0);
if (this.getWidth() != null) {
text.setWidth(this.getWidth() - 30);
}
Button img = new Button();
img.setXtype("button.IconTextButton");
img.width = (25);
img.setTop(1);
img.height = (text.getHeight());
if (text.getWidth() != null) {
img.setLeft(text.getWidth() + 1);
}
img.setHandler("OpenEditor");
_items.add(text);
_items.add(img);
}
return _items;
}
@Override
public void setDefaultVal(Map<String, Object> updrow) {
if (getItems() != null && !getItems().isEmpty()) {
((TextField) getItems().get(0)).setDefaultval(DataTableUtil.getRowVal(updrow, this.getName(), ""));
}
}
}
@@ -0,0 +1,57 @@
package org.example.Entity.Control.Fields;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.example.Utils.DataTableUtil;
import java.util.Map;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class TextField extends Field {
private String _emptyText;
private String type;
public TextField(Map<String, Object> row) {
super(row);
this.defaultXtype = "textfield";
}
@Override
public String getXtype() {
if (getName() == null || getName().isEmpty()) {
super.setXtype("displayfield");
}
return super.getXtype();
}
@Override
public void setXtype(String xtype) {
super.setXtype(xtype);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getMaxLength() {
Object m = DataTableUtil.getRowVal(_row, "limitmaxvalue", null);
return m != null && (Integer) m == 0 ? null : (Integer) m;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getEmptyText() {
return _emptyText;
}
public void setEmptyText(String emptyText) {
this._emptyText = emptyText;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
@@ -0,0 +1,30 @@
package org.example.Entity.Control.Fields;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.example.Utils.IPublicUtil;
import java.util.Map;
public class TextareaField extends TextField {
public TextareaField(Map<String, Object> row) {
super(row);
this.defaultXtype = "textareafield";
this._autoHeight = null;
}
private Boolean _autoHeight;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean getAutoHeight() {
return _autoHeight;
}
public void setAutoHeight(Boolean autoHeight) {
this._autoHeight = autoHeight;
}
}
@@ -0,0 +1,349 @@
package org.example.Entity.Control.Panel;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Base.RowComponent;
import org.example.Enums.SystemEnums;
import org.example.Utils.DataTableUtil;
import org.example.Utils.NativeExtensionUtils;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Objects;
import static org.example.Utils.NativeExtensionUtils.ToInt32;
import static org.example.Utils.NativeExtensionUtils.toBoolean;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Chart extends RowComponent {
public Chart(Map<String, Object> row) {
super(row);
}
@Override
public String getXtype() {
SystemEnums.ChartType chartType;
try {
chartType = SystemEnums.ChartType.fromValue(getCharttype());
switch (chartType) {
case Line:
case Bar:
return "chart.Bar";
case Pie:
return "chart.Pie";
case Funnel:
return "chart.Funnel";
default:
return "chart.Base";
}
} catch (Exception e) {
return "chart.Base";
}
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getSeriestype() {
try {
SystemEnums.ChartType chartType = SystemEnums.ChartType.fromValue(getCharttype());
if (chartType != null) {
return chartType.name().toLowerCase();
}
} catch (Exception e) {
return null;
}
return null;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object option;
public String _charttile;
public String getCharttitle() {
return (String) DataTableUtil.getRowVal(this._row, "charttitle", _charttile, null);
}
public void setCharttitle(String charttitle) {
this._charttile = charttitle;
}
private Integer _charttype;
@JsonIgnore
public int getCharttype() {
return ToInt32(DataTableUtil.getRowVal(this._row, "charttype", _charttype, 0));
}
public void setCharttype(int charttype) {
this._charttype = charttype;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getChartcolor() {
return (String) DataTableUtil.getRowVal(this._row, "chartcolor", null);
}
public void setChartcolor(String chartcolor) {
this._chartcolordf = (chartcolor);
}
private String _chartcolordf;
@JsonIgnore
public String getChartcolordf() {
return (String) DataTableUtil.getRowVal(this._row, "chartcolordf", _chartcolordf, null);
}
public void setChartcolordf(String chartcolordf) {
this._chartcolordf = chartcolordf;
}
private String _xlabelfield;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getXlabelfield() {
_xlabelfield = (String) DataTableUtil.getRowVal(this._row, "xlabelfield", _xlabelfield, null);
if (_xlabelfield != null && !_xlabelfield.isEmpty()) {
return _xlabelfield.toLowerCase();
}
return _xlabelfield;
}
public void setXlabelfield(String xlabelfield) {
this._xlabelfield = xlabelfield;
}
private String _yvaluefield;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getYvaluefield() {
_yvaluefield = (String) DataTableUtil.getRowVal(this._row, "yvaluefield", _yvaluefield, null);
if (_yvaluefield != null && !_yvaluefield.isEmpty()) {
_yvaluefield = _yvaluefield.toLowerCase();
}
return _yvaluefield;
}
public void setYvaluefield(String yvaluefield) {
this._yvaluefield = yvaluefield;
}
private String _yvaluefield1;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getYvaluefield1() {
_yvaluefield1 = (String) DataTableUtil.getRowVal(this._row, "yvaluefield1", _yvaluefield1, null);
if (_yvaluefield1 != null && !_yvaluefield1.isEmpty()) {
_yvaluefield1 = _yvaluefield1.toLowerCase();
}
return _yvaluefield1;
}
public void setYvaluefield1(String yvaluefield1) {
this._yvaluefield1 = yvaluefield1;
}
private String _yvaluefield2;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getYvaluefield2() {
_yvaluefield2 = (String) DataTableUtil.getRowVal(this._row, "yvaluefield2", _yvaluefield2, null);
if (_yvaluefield2 != null && !_yvaluefield2.isEmpty()) {
_yvaluefield2 = _yvaluefield2.toLowerCase();
}
return _yvaluefield2;
}
public void setYvaluefield2(String yvaluefield2) {
this._yvaluefield2 = yvaluefield2;
}
private String _xaxistitle;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getXaxistitle() {
return (String) DataTableUtil.getRowVal(this._row, "xaxistitle", _xaxistitle, null);
}
public void setXaxistitle(String xaxistitle) {
this._xaxistitle = xaxistitle;
}
private String _yaxistitle;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getYaxistitle() {
return (String) DataTableUtil.getRowVal(this._row, "yaxistitle", _yaxistitle, null);
}
public void setYaxistitle(String yaxistitle) {
this._yaxistitle = yaxistitle;
}
private String _yaxisshared;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getYaxisshared() {
Object value = DataTableUtil.getRowVal(_row, "yaxisshared", _yaxisshared);
return value != null ? value.toString() : null;
}
public void setYaxisshared(String yaxisshared) {
this._yaxisshared = yaxisshared;
}
private Integer _isabsolutely;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getIsabsolutely() {
Object val = DataTableUtil.getRowVal(_row, "isabsolutely", _isabsolutely);
return val != null ? (Integer) val : null;
}
public void setIsabsolutely(Integer isabsolutely) {
this._isabsolutely = isabsolutely;
}
private BigDecimal _yscale;
@JsonInclude(JsonInclude.Include.NON_NULL)
public BigDecimal getYscale() {
Object val = DataTableUtil.getRowVal(_row, "yscale", _yscale);
return val != null ? (BigDecimal) val : null;
}
public void setYscale(BigDecimal yscale) {
this._yscale = yscale;
}
private String _valueVisible;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getValueVisible() {
Object value = DataTableUtil.getRowVal(_row, "valuevisible", _valueVisible);
return value != null ? value.toString() : null;
}
public void setValueVisible(String valueVisible) {
this._valueVisible = valueVisible;
}
private Integer _xLabelFontSize;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getXLabelFontSize() {
if (_xLabelFontSize == null) {
_xLabelFontSize = ToInt32(DataTableUtil.get(this._row, "xLabelFontSize", 0));
}
return _xLabelFontSize > 0 ? _xLabelFontSize : null;
}
public void setXLabelFontSize(Integer xLabelFontSize) {
this._xLabelFontSize = xLabelFontSize;
}
private Integer _xLabelRotate;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getXLabelRotate() {
if (_xLabelRotate == null) {
_xLabelRotate = ToInt32(DataTableUtil.get(this._row, "xLabelRotate", 0));
}
return _xLabelRotate > 0 ? _xLabelRotate : null;
}
public void setXLabelRotate(Integer xLabelRotate) {
this._xLabelRotate = xLabelRotate;
}
private Boolean _xLablVisibel;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean getXLablVisibel() {
if (_xLablVisibel == null) {
_xLablVisibel = toBoolean(DataTableUtil.get(this._row, "xLablVisibel", 0));
}
return _xLablVisibel != null && _xLablVisibel ? false : null;
}
public void setXLablVisibel(Boolean xLablVisibel) {
this._xLablVisibel = xLablVisibel;
}
private Boolean _legendVisible;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean getLegendVisible() {
if (_legendVisible == null) {
_legendVisible = toBoolean(DataTableUtil.get(this._row, "legendvisible", 0));
}
return _legendVisible != null && _legendVisible ? false : null;
}
public void setLegendVisible(Boolean legendVisible) {
this._legendVisible = legendVisible;
}
private Boolean _xLabelInterval;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean getXLabelInterval() {
if (_xLabelInterval == null) {
_xLabelInterval = toBoolean(DataTableUtil.get(this._row, "labelSpaced", 0));
}
return _xLabelInterval != null && _xLabelInterval ? _xLabelInterval : null;
}
public void setXLabelInterval(Boolean xLabelInterval) {
this._xLabelInterval = xLabelInterval;
}
private Integer _pieRadius;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getPieRadius() {
if (_pieRadius == null) {
_pieRadius = ToInt32(DataTableUtil.get(this._row, "circlehollow", 0));
}
return _pieRadius > 0 ? _pieRadius : null;
}
public void setPieRadius(Integer pieRadius) {
this._pieRadius = pieRadius;
}
private String _pieRoseType;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getPieRoseType() {
if (_pieRoseType == null) {
_pieRoseType = Objects.toString(DataTableUtil.get(this._row, "circlejagge", 0), "").toLowerCase();
}
if (_pieRoseType != null && !_pieRoseType.isEmpty()) {
switch (_pieRoseType) {
case "radius":
return "radius";
case "area":
return "area";
default:
return "radius";
}
}
return null;
}
public void setPieRoseType(String pieRoseType) {
this._pieRoseType = pieRoseType;
}
}
@@ -0,0 +1,209 @@
package org.example.Entity.Control.Panel;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Base.Component;
import org.example.Entity.Control.Container.RowColumn;
import org.example.Entity.Control.Data.DataStore;
import org.example.Entity.Control.Fields.ComboBox;
import java.util.*;
import java.util.stream.Collectors;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class GridPanel extends Panel {
public GridPanel() {
super();
this.setXtype("gridpanel");
}
public boolean PageAble;
@JsonInclude(JsonInclude.Include.NON_NULL) // 对应Newtonsoft.Json的NullValueHandling.Ignore
private List<Component> _columns;
@JsonInclude(JsonInclude.Include.NON_NULL)
public List<Component> getColumns() {
return _columns;
}
public void setColumns(List<Component> value) {
_columns = value;
if (value != null) {
List<String> bandNames = new ArrayList<>();
List<Component> cols = new ArrayList<>();
// 筛选包含bandFields的列并处理
List<Component> f = value.stream()
.filter(col -> col instanceof RowColumn)
.map(col -> (RowColumn) col)
.filter(column -> column.getBandFields() != null && column.getBandFields().length > 0)
.map(column -> {
String[] bfields = column.getBandFields();
Collections.addAll(bandNames, bfields);
// 收集关联的列
List<Component> relatedCols = value.stream()
.filter(cl -> cl instanceof RowColumn)
.map(cl -> (RowColumn) cl)
.filter(c -> Arrays.asList(bfields).contains(c.getDataIndex()))
.collect(Collectors.toList());
cols.addAll(relatedCols);
return (Component) column; // 转回Component类型
})
.collect(Collectors.toList());
// 处理下拉框列的联动关系
List<RowColumn> comboboxColumns = value.stream()
.filter(col -> col instanceof RowColumn)
.map(col -> (RowColumn) col)
.filter(column -> column.getEditor() != null && column.getEditor() instanceof ComboBox)
.collect(Collectors.toList());
for (RowColumn column : comboboxColumns) {
String target = "{" + column.getDataIndex() + "}";
String[] linkNames = comboboxColumns.stream()
.filter(_com -> column != _com) // 排除自身
.filter(_com -> {
ComboBox comboBox = (ComboBox) _com.getEditor();
String dataSource = comboBox.getDataSource();
return dataSource != null &&
dataSource.toLowerCase().contains(target.toLowerCase());
})
.map(_com -> _com.getDataIndex())
.toArray(String[]::new);
column.linknames = (linkNames);
}
if (f.size() <= 0) {
return;
}
// 添加未被bandNames包含的列
List<Component> remainingCols = value.stream()
.filter(col -> col instanceof RowColumn)
.map(col -> (RowColumn) col)
.filter(c -> !bandNames.contains(c.getDataIndex()))
.map(c -> (Component) c) // 转回Component类型
.collect(Collectors.toList());
cols.addAll(remainingCols);
// 如需替换_columns,取消下面注释
// _columns = cols;
}
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public List<Component> CardColumns;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object MobileCards;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object data;
private DataStore _store;
@JsonInclude(JsonInclude.Include.NON_NULL)
public DataStore getStore() {
if (getColumns() != null && !getColumns().isEmpty()) {
if (_store == null) {
_store = new DataStore();
}
if (_store.fields == null) {
_store.fields = (getColumns().stream()
.filter(col -> col instanceof RowColumn)
.map(col -> ((RowColumn) col).getStoreField())
.toArray(Object[]::new));
}
}
return _store;
}
public void setStore(DataStore store) {
this._store = store;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object RightMenu;
public int SHeight;
public String IdField;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String displayField;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object TbarItems;
@JsonInclude(JsonInclude.Include.NON_NULL)
public List<Object> BbarItems;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object DefaultSearchBoxData;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("Calc")
public Object getCalc() {
if (getColumns() != null && !getColumns().isEmpty()) {
Map<String, String> calcDict = new HashMap<>();
getColumns().stream()
.filter(col -> col instanceof RowColumn && ((RowColumn) col).getCalcExpr() != null && !((RowColumn) col).getCalcExpr().isEmpty())
.sorted(Comparator.comparingInt(col -> ((RowColumn) col).getCalcOrder()))
.map(col -> (RowColumn) col)
.forEach(col -> {
if (!calcDict.containsKey(col.getFieldName())) {
calcDict.put(col.getFieldName(), col.getCalcExpr());
}
});
return calcDict;
}
return null;
}
protected Boolean isSum() {
if (getColumns() != null && !getColumns().isEmpty()) {
return getColumns().stream()
.anyMatch(col -> col instanceof RowColumn && ((RowColumn) col).isIsSum());
}
return false;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object ChartCfg;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean NoGridLine = null;
private Boolean _hideColumnHeader;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean getHideColumnHeader() {
return _hideColumnHeader != null && _hideColumnHeader ? true : null;
}
public void setHideColumnHeader(Boolean hideColumnHeader) {
this._hideColumnHeader = hideColumnHeader;
}
private Boolean _rowNumberer = null;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean getRowNumberer() {
return _rowNumberer != null && !_rowNumberer ? false : null;
}
public void setRowNumberer(Boolean rowNumberer) {
this._rowNumberer = rowNumberer;
}
public Integer displayRows;
}
@@ -0,0 +1,26 @@
package org.example.Entity.Control.Panel;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Base.Component;
/**
* ==============================================================================
* 功能描述:Panel
* ==============================================================================
*/
public class Panel extends Component {
public Panel() {
super();
this.defaultXtype = "panel";
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public String title;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ElseValue")
public Object elseValue;
}
@@ -0,0 +1,37 @@
package org.example.Entity.Control.Panel;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Data.DataStore;
/**
* ==============================================================================
* 功能描述:TreePanel
* ==============================================================================
*/
public class TreePanel extends Panel {
public TreePanel() {
super();
this.defaultXtype = "treepanel";
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public String displayField;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String valueField;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String parentValueField;
@JsonInclude(JsonInclude.Include.NON_NULL)
public DataStore store;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object TbarItems;
}
@@ -0,0 +1,34 @@
package org.example.Entity.Control.Validators;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* ==============================================================================
* 功能描述:Base
* ==============================================================================
*/
public class Length extends VBase {
public Length() {
super();
this.type = "length";
}
public int min;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer max;
public String bothMessage;
public String emptyMessage;
public String maxOnlyMessage;
public String minOnlyMessage;
}
@@ -0,0 +1,24 @@
package org.example.Entity.Control.Validators;
import com.fasterxml.jackson.annotation.JsonInclude;
/**
* ==============================================================================
* 功能描述:VBase
* 创 建 者:zyw
* 创建日期:2016-09-21 16:33:57
* ==============================================================================
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class VBase {
public VBase() {
}
public VBase(String type) {
this.type = type;
}
public String type;
}
@@ -0,0 +1,25 @@
package org.example.Entity.CusException;
public class CusException extends Exception {
/**
* 是否继续执行
*/
public boolean Continue;
/**
* 是否记录日志
*/
public boolean Log;
public CusException() {
super();
}
public CusException(String message) {
super(message);
}
public CusException(String message, Throwable innerException) {
super(message, innerException);
}
}
@@ -0,0 +1,14 @@
package org.example.Entity;
/**
* 基础事件参数类,对应C#的EventArgs
*/
public class EventArgs {
// 可以根据需要添加通用的事件参数属性和方法
private static final EventArgs EMPTY = new EventArgs();
public static EventArgs empty() {
return EMPTY;
}
}
@@ -0,0 +1,138 @@
package org.example.Entity.Node;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.example.Utils.DataTableUtil;
import org.example.Utils.DbOperator;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
import java.util.Map;
/**
* ==============================================================================
* 功能描述:TreeNode 树形结构的节点
* 创 建 者:zyw
* 创建日期:2016-11-24 11:31:26
* ==============================================================================
*/
public class TreeNode {
private JdbcTemplate jdbcTemplate;
private String countSql;
private String idField;
private String displayField;
private Map<String, Object> row; // 对应DataRow,使用数组或Map存储行数据
private DbOperator dbOperator;
public TreeNode() {
}
public TreeNode(Map<String, Object> row, String idField, String displayField, JdbcTemplate jdbcTemplate, String countSql) {
this.row = row;
this.idField = idField;
this.displayField = displayField;
this.jdbcTemplate = jdbcTemplate;
this.countSql = countSql;
this.dbOperator = new DbOperator(jdbcTemplate);
}
private String speciesno;
/**
* 树的主键
*/
public String getSpeciesno() {
if (speciesno == null || speciesno.isEmpty()) {
speciesno = DataTableUtil.getRowVal(row, new String[]{idField, "speciesno"}, "") + "";
}
return speciesno;
}
public void setSpeciesno(String speciesno) {
this.speciesno = speciesno;
}
private String speciesname;
/**
* 树的显示名
*/
public String getSpeciesname() {
if (speciesname == null || speciesname.isEmpty()) {
speciesname = DataTableUtil.getRowVal(row, new String[]{displayField, "speciesname"}, "") + "";
}
return speciesname;
}
public void setSpeciesname(String speciesname) {
this.speciesname = speciesname;
}
@JsonIgnore
public String parentno;
private boolean checked;
/**
* 复选框
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean getChecked() {
if (!checkbox) {
return null;
}
return checked;
}
public void setChecked(Boolean checked) {
this.checked = checked != null ? checked : false;
}
private boolean checkbox = true;
@JsonIgnore
public boolean isCheckbox() {
return checkbox;
}
public void setCheckbox(boolean checkbox) {
this.checkbox = checkbox;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean expanded;
@JsonInclude(JsonInclude.Include.NON_NULL)
public List<TreeNode> children;
/**
* 叶节点标识
*/
private Boolean leaf = null;
public boolean isLeaf() {
if (leaf == null) {
if (countSql != null && !countSql.isEmpty()) {
// 执行计数查询判断是否为叶节点
String sql = dbOperator.BuildCountSql(countSql);
Integer count = jdbcTemplate.queryForObject(sql, new Object[]{speciesno}, Integer.class);
leaf = count <= 0;
} else {
// 无计数SQL时根据子节点判断
leaf = !(children != null && !children.isEmpty());
}
}
return leaf != null ? leaf : false;
}
public void setLeaf(boolean leaf) {
this.leaf = leaf;
}
/**
* 其他需要传递给控件的参数
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object ElseValue;
}
@@ -0,0 +1,68 @@
package org.example.Entity.System.Audit;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Map;
import static org.example.Utils.DataTableUtil.get;
import static org.example.Utils.NativeExtensionUtils.ToInt32;
import static org.example.Utils.NativeExtensionUtils.isNullOrEmpty;
public class AuditBase {
public AuditBase(Map<String, Object> row) {
super();
this.row = row;
}
protected Map<String, Object> row;
public Integer getItemId() {
return ToInt32(get(row, "id", "0"));
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("TypeCode")
public String getTypeCode() {
return (String) get(row, "typecode", "");
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("StepName")
public String getStepName() {
return (String) get(row, "stepname", "");
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("StepCode")
public String getStepCode() {
String _stepCode = get(row, "stepcode", "") + "";
if (isNullOrEmpty(_stepCode)) return null;
return _stepCode;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("StepGroup")
public String getStepGroup() {
return (String) get(row, "StepGroup", "");
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ViewUser")
public String getViewUser() {
return (String) get(row, "ViewUser", "");
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("OperUser")
public String getOperUser() {
return (String) get(row, "OperUser", "");
}
@JsonIgnore
public String getPStepCode() {
return (String) get(row, "PStepCode", "");
}
}
@@ -0,0 +1,135 @@
package org.example.Entity.System.Audit;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.Map;
import static org.example.Utils.DataTableUtil.get;
import static org.example.Utils.NativeExtensionUtils.toBoolean;
public class AuditStep extends AuditBase {
public AuditStep(Map<String, Object> row) {
super(row);
}
@JsonIgnore
public String getStepAction() {
return (String) get(row, "StepAction", "");
}
@JsonIgnore
public String getBackAction() {
return (String) get(row, "backAction", "");
}
@JsonIgnore
public String getStepSql() {
return (String) get(row, "stepSql", "");
}
@JsonIgnore
public String getBillModifyFields() {
return (String) get(row, "billModifyFields", "");
}
@JsonIgnore
public String getRequiredFields() {
return (String) get(row, "requiredFields", "");
}
;//+get
@JsonIgnore
public String getRequiredDetailFields() {
return (String) get(row, "requiredDetailFields", "");
}
;//+get
@JsonIgnore
public String getDetailModifyFields() {
return (String) get(row, "detailModifyFields", "");
}
;//+get
@JsonIgnore
public String getBeforeEvent() {
return (String) get(row, "beforeEvent", "");
}
;//+get
@JsonIgnore
public String getAfterEvent() {
return (String) get(row, "afterEvent", "");
}
;//+get
@JsonIgnore
public String getStepApplyText() {
return (String) get(row, "StepApplyText", "");
}
;//+get
@JsonIgnore
public String getStepBackText() {
return (String) get(row, "stepBackText", "");
}
;//+get
@JsonIgnore
public String getStepApplyContent() {
return (String) get(row, "stepApplyContent", "");
}
;//+get
@JsonIgnore
public String getStepBackContent() {
return (String) get(row, "stepBackContent", "");
}
@JsonIgnore
public String getStepCloseText() {
return (String) get(row, "stepCloseText", "");
}
@JsonIgnore
public String getStepCloseContent() {
return (String) get(row, "stepCloseContent", "");
}
@JsonIgnore
public String getStepCloseTip() {
return (String) get(row, "stepCloseTip", "");
}
;//+get
@JsonIgnore
public String getAuditContent() {
return (String) get(row, "auditContent", "");
}
;//+get
@JsonIgnore
public Boolean getIsLocked() {
return (Boolean) get(row, "isLocked", "");
}
;//+get
@JsonIgnore
public boolean getDisJCP() {
return toBoolean(get(row, "disjcp", ""));
}
}
@@ -0,0 +1,65 @@
package org.example.Entity.System.Audit;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.Map;
import static org.example.Utils.DataTableUtil.get;
import static org.example.Utils.NativeExtensionUtils.ToInt32;
public class AuditTypeStep extends AuditBase {
public AuditTypeStep(Map<String, Object> row) {
super(row);
}
@JsonIgnore
public int getBillType() {
return ToInt32(get(row, "id", "0"));
}
;//+get
@JsonIgnore
public String getStepBackCode() {
return (String) get(row, "stepBackCode", "");
}
;//+get
@JsonIgnore
public String getStepTime() {
return get(row, "StepTime", "") + "";
}
;//+get
@JsonIgnore
public Boolean getAutoStep() {
return (Boolean) get(row, "AutoStep", false);
}
;//+get
@JsonIgnore
public String getTypeKey() {
return get(row, "typeKey", "") + "";
}
;//+get
@JsonIgnore
public String getStepOverCond() {
return (String) get(row, "StepOverCond", "");
}
;//+get
@JsonIgnore
public String getAutoStepCond() {
return (String) get(row, "AutoStepCond", "");
}
;//+get
}
@@ -0,0 +1,171 @@
package org.example.Entity.System;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import java.util.Map;
import static org.example.Utils.DataTableUtil.get;
import static org.example.Utils.DataTableUtil.getStringValue;
import static org.example.Utils.NativeExtensionUtils.ToInt32;
import static org.example.Utils.NativeExtensionUtils.toBoolean;
public class BaseDetailModule extends ModuleEntity {
public BaseDetailModule() {
super();
}
public BaseDetailModule(Map<String, Object> row) {
super(row);
}
@JsonIgnore
public String getDetailId() {
return getStringValue(basemodule, "id", null, null);
}
private String _unionKey;
@JsonIgnore
public void setUnionKey(String unionKey) {
this._unionKey = unionKey;
}
public String getUnionKey() {
return getStringValue(basemodule, "unionkey", _unionKey, null);
}
private String _unionMenuCode;
public String getUnionMenuCode() {
return (String) get(basemodule, "UnionMenuCode", _unionMenuCode, null);
}
public void setUnionMenuCode(String unionMenuCode) {
this._unionMenuCode = unionMenuCode;
}
private String _unionField;
public String getUnionField() {
return (getStringValue(basemodule, "UnionField", _unionField, null)).toLowerCase();
}
public void setUnionField(String unionField) {
this._unionField = unionField;
}
private String _unionParentField;
@JsonProperty("UnionParentField")
public String getUnionParentField() {
return (getStringValue(basemodule, "UnionParentField", _unionParentField, null)).toLowerCase();
}
public void setUnionParentField(String unionParentField) {
this._unionParentField = unionParentField;
}
private String _unionValue;
public String getUnionValue() {
return (getStringValue(basemodule, "UnionValue", _unionValue, null)).toLowerCase();
}
public void setUnionValue(String unionValue) {
this._unionValue = unionValue;
}
private String _unionSql;
/// <summary>
/// 明细sql
/// </summary>
public String getUnionSql() {
return (String) get(basemodule, "UnionSQL", _unionSql, null);
}
public void setUnionSql(String unionSql) {
this._unionSql = unionSql;
}
private String _unionCond;
/// <summary>
/// 主表关联明细的条件,有条件就不用关联字段
/// </summary>
public String getUnionCond() {
return (String) get(basemodule, "unionCond", _unionCond, null);
}
public void setUnionCond(String unionCond) {
this._unionCond = unionCond;
}
private Integer _unionType;
public Integer getUnionType() {
return ToInt32(get(basemodule, "detailType", _unionType, null));
}
public void setUnionType(Integer unionType) {
this._unionType = unionType;
}
private Boolean _refresh;
public Boolean getRefresh() {
return toBoolean(get(basemodule, "Refresh", _refresh, null));
}
public void setRefresh(Boolean refresh) {
this._refresh = refresh;
}
private Boolean _addFlag;
public Boolean getAddFlag() {
return toBoolean(get(basemodule, "AddFlag", _addFlag, null));
}
public void setAddFlag(Boolean addFlag) {
this._addFlag = addFlag;
}
private Integer _displayrows;
public Integer getDisPlayRows() {
return ToInt32(get(basemodule, "displayrows", _displayrows, null));
}
public void setDisPlayRows(Integer displayrows) {
this._displayrows = displayrows;
}
}
@@ -0,0 +1,982 @@
package org.example.Entity.System;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Base.Component;
import org.example.Enums.SystemTypeEnums;
import org.example.Utils.DataTableUtil;
import org.example.Utils.JsEngine;
import org.example.Utils.PublicUtil;
import java.util.Map;
import static com.microsoft.sqlserver.jdbc.StringUtils.isEmpty;
import static io.micrometer.common.util.StringUtils.isNotEmpty;
import static org.example.Utils.DataTableUtil.get;
import static org.example.Utils.NativeExtensionUtils.*;
public class BaseModule extends ModuleBaseEntity {
public BaseModule(Map<String, Object> basemodule) {
super(basemodule);
this.basemodule = basemodule;
}
public BaseModule() {
super();
}
Map<String, Object> basemodule;
@JsonProperty("IdField")
@Override
public String getIdField() {
if (getUnionBillCode() == null) {
return super.getIdField();
}
return "billid";
}
@Override
public void setIdField(String idField) {
super.setIdField(idField);
}
@JsonProperty("IsSpecModule")
public boolean IsSpecModule;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String detailId;
private String _condKey;
@JsonIgnore
@JsonProperty("CondKey")
public String getCondKey() {
Object _fk = get(basemodule, "condkey", _condKey);
if (_fk != null && !(_fk + "").isEmpty()) {
_condKey = _fk + "";
return _condKey;
}
return null;
}
@JsonProperty("PageAble")
public boolean getPageAble() {
return toBoolean(DataTableUtil.get(basemodule, "pagerflag", true));
}
@JsonProperty("PageSize")
public int getPageSize() {
return ToInt32(DataTableUtil.get(basemodule, "pagesize", true));
}
@JsonProperty("SelectLeaf")
public int getSelectLeaf() {
return ToInt32(get(basemodule, "selectLeaf", true));
}
private Boolean _selfEdit;
@JsonProperty("SelfEdit")
public boolean isSelfEdit() {
if (_selfEdit != null) {
return _selfEdit;
}
boolean editFlag = toBoolean(get(basemodule, "EditFlag", false));
_selfEdit = (isSaveAble() && (isUpdateAble() || isAddAble())) && editFlag;
return _selfEdit;
}
public void setSelfEdit(boolean value) {
this._selfEdit = value;
}
@JsonProperty("ModuleType")
public Integer ModuleType = 0;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String Title;
@JsonProperty("Title")
public String getTitle() {
return getMenuName();
}
public void setTitle(String value) {
this.Title = value;
}
private String _unionBillCode;
@JsonProperty("UnionBillCode")
public String getUnionBillCode() {
if (_unionBillCode == null) {
Object value = get(basemodule, "UnionBillCode", _unionBillCode);
_unionBillCode = (value != null) ? value.toString() : null;
}
return _unionBillCode;
}
private String _masterTab;
@JsonIgnore
@JsonProperty("MasterTable")
@Override
public String getMasterTable() {
return (String) get(basemodule, "TableName", _masterTab);
}
@Override
public void setMasterTable(String value) {
this._masterTab = value;
}
private String _masterSql;
@JsonIgnore
@JsonProperty("MasterSql")
public String getMasterSql() {
return (String) get(basemodule, "TableSQL", _masterSql);
}
public void setMasterSql(String MasterSql) {
this._masterSql = MasterSql;
}
private String _apiDataNode;
@JsonIgnore
@JsonProperty("ApiDataNode")
public String getApiDataNode() {
return (String) get(basemodule, "apiDataNode", _apiDataNode);
}
public void setApiDataNode(String apiDataNode) {
_apiDataNode = apiDataNode;
}
private String _apiSuccNode;
@JsonIgnore
@JsonProperty("ApiSuccNode")
public String getApiSuccNode() {
return (String) get(basemodule, "apiSuccNode", _apiSuccNode);
}
public void setApiSuccNode(String apiSuccNode) {
this._apiSuccNode = apiSuccNode;
}
private String _apiSuccVal;
@JsonIgnore
@JsonProperty("ApiSuccVal")
public String getApiSuccVal() {
return (String) get(basemodule, "apiSuccVal", _apiSuccVal);
}
public void setApiSuccVal(String value) {
this._apiSuccVal = value;
}
private Integer _menuType;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("MenuType")
public Integer getMenuType() {
return (Integer) get(basemodule, "MenuType", _menuType);
}
public void setMenuType(Integer menuType) {
_menuType = menuType;
}
private Boolean _isReport;
@JsonProperty("IsReport")
public boolean isIsReport() {
Object value = get(basemodule, "ReportFlag", false);
this._isReport = toBoolean(value);
return _isReport;
}
public void setIsReport(Boolean IsReport) {
this._isReport = IsReport;
}
private String _addCond;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("AddCond")
public String getAddCond() {
if (_addCond != null && !_addCond.isEmpty()) {
return _addCond;
}
_addCond = (String) get(basemodule, "AddCond", _addCond);
_addCond = PublicUtil.ReqSqlPmsByRow(null, null, PublicUtil.SqlToCode(_addCond), SystemTypeEnums.PmType.ignorenull);
if (_addCond != null && _addCond.indexOf("{") < 0) {
if (_addCond == null || _addCond.isEmpty()) {
_addCond = "1==1";
}
}
return _addCond;
}
public void setAddCond(String value) {
this._addCond = value;
}
private Boolean _updateAble = null;
@JsonProperty("UpdateAble")
public boolean isUpdateAble() {
if (toBoolean(!OperAble)) {
return false;
}
if (_updateAble != null) {
return _updateAble;
}
if (toBoolean(!isSaveAble())) {
return false;
}
if (isNotEmpty(getUpdateCond())) {
return !isIsReport();
} else {
if (!getUpdateCond().contains("{")) {
_updateAble = toBoolean(JsEngine.Eval(getUpdateCond()));
} else {
return !isIsReport();
}
return _updateAble != null && _updateAble && !isIsReport();
}
}
private String _updateCond = null;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("UpdateCond")
public String getUpdateCond() {
if (isNotEmpty(_updateCond)) {
return _updateCond;
}
Object value = get(basemodule, "UpdateCond", _updateCond);
_updateCond = (value != null) ? value.toString() : null;
_updateCond = PublicUtil.SqlToCode(_updateCond);
_updateCond = PublicUtil.ReqSqlPmsByRow(
null,
null,
_updateCond,
SystemTypeEnums.PmType.ignorenull
);
if (_updateCond != null && _updateCond.indexOf("{") < 0) {
if (isEmpty(_updateCond)) {
_updateCond = "1==1";
}
}
return _updateCond;
}
public void setUpdateCond(String updateCond) {
this._updateCond = updateCond;
}
private String _deleteCond;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("DeleteCond")
public String getDeleteCond() {
if (_deleteCond != null && !_deleteCond.isEmpty()) {
return _deleteCond;
}
_deleteCond = (String) get(basemodule, "DeleteCond", _deleteCond);
_deleteCond = PublicUtil.ReqSqlPmsByRow(null, null, PublicUtil.SqlToCode(_deleteCond),
SystemTypeEnums.PmType.ignorenull);
if (_deleteCond == null || !_deleteCond.contains("{")) {
if (_deleteCond == null || _deleteCond.isEmpty()) {
_deleteCond = "1==1";
}
}
return _deleteCond;
}
public void setDeleteCond(String value) {
this._deleteCond = value;
}
private String _applyCond;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ApplyCond")
public String getApplyCond() {
return (String) get(basemodule, "ApplyCond", _applyCond);
}
public void setApplyCond(String value) {
this._applyCond = value;
}
private String _copyCond;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("CopyCond")
public String getCopyCond() {
return (String) get(basemodule, "CopyCond", _copyCond);
}
public void setCopyCond(String value) {
this._copyCond = value;
}
private Boolean _addFlag;
@JsonProperty("AddAble")
public boolean isAddAble() {
if (!OperAble) {
return false;
}
Object addFlagValue = get(basemodule, "AddFlag");
if (addFlagValue == null) {
addFlagValue = (_addFlag != null) ? _addFlag : false;
}
boolean addable = toBoolean(addFlagValue);
if (!addable) {
return false;
}
if (isNullOrEmpty(getAddCond())) {
return !isIsReport();
} else if (getAddCond().indexOf("{") < 0) {
Object evalResult = PublicUtil.EvalCond(PublicUtil.SqlToCode(getAddCond()));
addable = toBoolean(evalResult);
}
return addable && !isIsReport();
}
public void setAddAble(Boolean value) {
this._addFlag = value;
}
@JsonIgnore
private Boolean _saveFlag;
@JsonProperty("SaveAble")
public boolean isSaveAble() {
return toBoolean(get(basemodule, "SaveFlag", _saveFlag, true));
}
public void setSaveAble(Boolean value) {
this._saveFlag = value;
}
private Boolean _deleteFlag;
@JsonProperty("DeleteAble")
public boolean getDeleteAble() {
if (!OperAble) return false;
boolean delable = toBoolean(get(basemodule, "DeleteFlag", _deleteFlag));
if (!delable) {
return false;
}
if (getDeleteCond() == null || getDeleteCond().isEmpty()) {
return !isIsReport();
} else if (!getDeleteCond().contains("{")) {
delable = toBoolean(PublicUtil.EvalCond(getDeleteCond()));
}
return delable && !isIsReport();
}
public void setDeleteAble(Boolean value) {
this._deleteFlag = value;
}
private Boolean _searchFlag;
@JsonProperty("SearchAble")
public boolean isSearchAble() {
Object value = get(basemodule, "searchable");
if (value == null) {
value = (_searchFlag != null) ? _searchFlag : true;
}
return toBoolean(value);
}
public void setSearchAble(Boolean value) {
this._searchFlag = value;
}
private Boolean _saveApplyFlag;
@JsonProperty("SaveApplyAble")
public boolean isSaveApplyAble() {
Object value = get(basemodule, "SaveApplyFlag");
if (value == null) {
value = (_saveApplyFlag != null) ? _saveApplyFlag : true;
}
return toBoolean(value);
}
public void setSaveApplyAble(Boolean value) {
this._saveApplyFlag = value;
}
private String _saveCaption;
@JsonProperty("saveText")
public String getSaveText() {
Object value = get(basemodule, "saveCapiton", _saveCaption, null);
return value == null ? null : value.toString();
}
public void setSaveCaption(String value) {
this._saveCaption = value;
}
private String _addCaption;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("addText")
public String getAddText() {
return (String) get(basemodule, "addCaption", _addCaption);
}
public void setAddText(String value) {
this._addCaption = value;
}
private String _modifyCaption;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("modifyText")
public String getModifyText() {
return (String) get(basemodule, "modifyCaption", _modifyCaption);
}
public void setModifyText(String value) {
this._modifyCaption = value;
}
private String _applyCaption;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("applyText")
public String getApplyText() {
return (String) get(basemodule, "applyCaption", _applyCaption, null);
}
public void setApplyText(String value) {
this._applyCaption = value;
}
private String _delCaption;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("delText")
public String getDelText() {
return (String) get(basemodule, "delCaption", _delCaption);
}
public void setDelText(String value) {
this._delCaption = value;
}
private String _printFile;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("PrintFile")
public String getPrintFile() {
return (String) get(basemodule, "PrintFile", _printFile);
}
public void setPrintFile(String value) {
this._printFile = value;
}
private Integer _printType;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("PrintType")
public Integer getPrintType() {
Object value = get(basemodule, "PrintType", _printType);
return value != null ? ToInt32(value) : null;
}
public void setPrintType(Integer value) {
this._printType = value;
}
private String _printSql;
@JsonIgnore
@JsonProperty("PrintSql")
public String getPrintSql() {
return (String) get(basemodule, "PrintSQL", _printSql);
}
public void setPrintSql(String value) {
this._printSql = value;
}
private String _printSql2;
@JsonIgnore
@JsonProperty("PrintSql2")
public String getPrintSql2() {
return (String) get(basemodule, "PrintSQL2", _printSql2);
}
public void setPrintSql2(String value) {
this._printSql2 = value;
}
private String _printSql3;
@JsonIgnore
@JsonProperty("PrintSql3")
public String getPrintSql3() {
return (String) get(basemodule, "PrintSQL3", _printSql3);
}
public void setPrintSql3(String value) {
this._printSql3 = value;
}
private Integer _leftWidth;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("LeftWidth")
public Integer getLeftWidth() {
Object value = get(basemodule, "LeftWidth", _leftWidth);
return value != null ? ToInt32(value) : null;
}
public void setLeftWidth(Integer value) {
this._leftWidth = value;
}
private Integer topHeight;
@JsonProperty("TopHeight")
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getTopHeight() {
Object value = get(basemodule, "TopHeight", topHeight, null);
return value instanceof Integer ? (Integer) value : (value != null ? ToInt32(value) : null);
}
public void setTopHeight(Integer topHeight) {
this.topHeight = topHeight;
}
private Integer popupWidth;
@JsonProperty("PopupWidth")
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getPopupWidth() {
Object value = get(basemodule, "pWidth", popupWidth, null);
return value instanceof Integer ? (Integer) value : (value != null ? ToInt32(value) : null);
}
public void setPopupWidth(Integer popupWidth) {
this.popupWidth = popupWidth;
}
private Integer popupHeight;
@JsonProperty("PopupHeight")
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getPopupHeight() {
Object value = get(basemodule, "pHeight", popupHeight, null);
return value instanceof Integer ? (Integer) value : (value != null ? ToInt32(value) : null);
}
public void setPopupHeight(Integer popupHeight) {
this.popupHeight = popupHeight;
}
private Integer winWidth;
@JsonProperty("WinWidth")
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getWinWidth() {
Object value = get(basemodule, "winWidth", winWidth, null);
return value instanceof Integer ? (Integer) value : (value != null ? ToInt32(value) : null);
}
public void setWinWidth(Integer winWidth) {
this.winWidth = winWidth;
}
private Integer winpHeight;
@JsonProperty("WinHeight")
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getWinHeight() {
Object value = get(basemodule, "winHeight", winpHeight, null);
return value instanceof Integer ? (Integer) value : (value != null ? ToInt32(value) : null);
}
public void setWinHeight(Integer winpHeight) {
this.winpHeight = winpHeight;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer OrderId;
private String _operPurview;
@JsonIgnore
@JsonProperty("OperPurview")
public String getOperPurview() {
return (String) get(basemodule, "OperPurview", _operPurview);
}
public void setOperPurview(String value) {
this._operPurview = value;
}
private String _readPurview;
@JsonIgnore
@JsonProperty("ReadPurview")
public String getReadPurview() {
return (String) get(basemodule, "ReadPurview", _readPurview);
}
public void setReadPurview(String value) {
this._readPurview = value;
}
private String _addModuleId;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("AddModuleId")
public String getAddModuleId() {
return (String) get(basemodule, "addmodid", _addModuleId);
}
public void setAddModuleId(String value) {
this._addModuleId = value;
}
private Boolean _closeAfterModify;
@JsonProperty("UpdClose")
public Boolean getUpdClose() {
_closeAfterModify = (_closeAfterModify == null)
? toBoolean(get(basemodule, "closeAfterModify", _closeAfterModify))
: _closeAfterModify;
return Boolean.TRUE.equals(_closeAfterModify) ? _closeAfterModify : null;
}
public void setUpdClose(Boolean value) {
this._closeAfterModify = value;
}
private Boolean _closeAfterAdd;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("AddClose")
public Boolean getAddClose() {
if (_closeAfterAdd == null) {
Object value = get(basemodule, "closeAfterAdd", _closeAfterAdd);
_closeAfterAdd = toBoolean(value);
}
return Boolean.TRUE.equals(_closeAfterAdd) ? _closeAfterAdd : null;
}
public void setAddClose(Boolean value) {
this._closeAfterAdd = value;
}
private Boolean _noDetail;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("NoDetail")
public Boolean getNoDetail() {
_noDetail = (_noDetail == null)
? toBoolean(get(basemodule, "disableDetail", _noDetail))
: _noDetail;
return Boolean.TRUE.equals(_noDetail) ? _noDetail : null;
}
public void setNoDetail(Boolean value) {
this._noDetail = value;
}
private Integer _scanMode;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ScanMode")
public Integer getScanMode() {
if (_scanMode == null) {
Object value = get(basemodule, "scanMode", null);
_scanMode = value != null ? ToInt32(value) : 0;
}
return _scanMode == 0 ? null : _scanMode;
}
public void setScanMode(Integer value) {
this._scanMode = value;
}
private Integer _scanNoRepet;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ScanNoRepet")
public Integer getScanNoRepet() {
Object value = get(basemodule, "scanNoRepet", _scanNoRepet);
return value != null ? ToInt32(value) : _scanNoRepet;
}
public void setScanNoRepet(Integer value) {
this._scanNoRepet = value;
}
private Integer _scanUnique;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ScanUnique")
public Integer getScanUnique() {
Object value = get(basemodule,"ScanUnique", _scanUnique);
return value != null ? ToInt32(value) : _scanUnique;
}
public void setScanUnique(Integer value) {
this._scanUnique = value;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ScanChar")
public String getScanChar() {
return (String) get(basemodule, "scanChar", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ScanFields")
public String getScanFields() {
return (String) get(basemodule, "scanFields", null);
}
private Boolean _disMobileTpl;
@JsonIgnore
@JsonProperty("DisMobileTpl")
public Boolean getDisMobileTpl() {
if (_disMobileTpl == null) {
_disMobileTpl = toBoolean(get(basemodule, "DisMobileCard", false));
}
return _disMobileTpl;
}
public void setDisMobileTpl(Boolean value) {
this._disMobileTpl = value;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("UnionField")
public String getUnionField(){
return DetailModule == null ? null : DetailModule.getUnionField();
};
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("UnionParentField")
public String getUnionParentField() {
return DetailModule == null ? null : DetailModule.getUnionParentField();
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("LeftUnionField")
public String LeftUnionField;
@JsonIgnore
@JsonProperty("LeftUnionFieldSql")
public String LeftUnionFieldSql;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("Left")
public Component Left;
// @JsonIgnore
@JsonProperty("Main")
public Component Main;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("Details")
public Object Details;
private Integer _bottomHeight;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("BottomHeight")
public Integer getBottomHeight() {
Object value = get(basemodule, "bottomHeight", _bottomHeight);
return value != null ? ToInt32(value) : null;
}
public void setBottomHeight(Integer value) {
this._bottomHeight = value;
}
private Integer detailPageAlign;
@JsonProperty("DetailPageAlign")
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer getDetailPageAlign() {
Object value = get(basemodule, "detailPageAlign", detailPageAlign, null);
return value instanceof Integer ? (Integer) value : (value != null ? ToInt32(value) : null);
}
public void setDetailPageAlign(Integer detailPageAlign) {
this.detailPageAlign = detailPageAlign;
}
private Integer _appAutoSave;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("scanAutoSave")
public Integer getScanAutoSave() {
if (_appAutoSave == null) {
Object value = DataTableUtil.getRowVal(basemodule, "appAutoSave", null);
if (value != null) {
_appAutoSave = ToInt32(value);
}
}
return _appAutoSave;
}
public void setScanAutoSave(Integer scanAutoSave) {
this._appAutoSave = scanAutoSave;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("MainDataColumns")
public Object MainDataColumns;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("AttCfgs")
public Object AttCfgs;
@JsonIgnore
@JsonProperty("IsCard")
public boolean IsCard;
private Boolean _multCheck;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("MultCheck")
public Boolean getMultCheck() {
if (_multCheck != null) return _multCheck;
_multCheck = toBoolean(get(basemodule, "MultCheck", false));
return !_multCheck ? null : _multCheck;
}
public void setMultCheck(Boolean value) {
this._multCheck = value;
}
private Boolean _refreshAll;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("RefreshAll")
public Boolean getRefreshAll() {
if (_refreshAll != null) return _refreshAll;
_refreshAll = toBoolean(get(basemodule, "RefreshAll"));
if (!(boolean) _refreshAll) return null;
return _refreshAll;
}
public void setRefreshAll(boolean value) {
_refreshAll = value;
}
@JsonProperty("IsChart")
public boolean IsChart;
@JsonIgnore
@JsonProperty("MainModifyFields")
public String MainModifyFields;
@JsonProperty("IsBase")
public boolean IsBase = true;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ModuleTabs")
public Object ModuleTabs;
private Boolean _appPrint;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("AppPrint")
public Boolean IsAppPrint() {
_appPrint = _appPrint == null ? toBoolean(get(basemodule,"appPrint", _appPrint,null)) : _appPrint;
if(_appPrint == true){
return _appPrint;
}
return null;
}
public void setAppPrint(Boolean value) {
this._appPrint = value;
}
private Integer _appPrintType;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("appPrintType")
public Integer getappPrintType() {
int t = ToInt32(get(basemodule,"appPrintType", _appPrintType,null));
if(t>0){
return t;
}
return null;
}
public void setappPrintType(Integer value) {
this._appPrintType = value;
}
private Integer _scanReadOnly;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("scanReadOnly")
public Integer getscanReadOnly() {
int t = ToInt32(get(basemodule,"scanReadOnly", _scanReadOnly,null));
if(t>0){
return t;
}
return null;
}
public void setscanReadOnly(Integer value) {
this._scanReadOnly = value;
}
// 2026.2.5 新增mrpType
public Integer mrpType;
}
@@ -0,0 +1,25 @@
package org.example.Entity.System;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
//import org.bytedeco.opencv.presets.opencv_core;
import org.example.Utils.DataTableUtil;
import java.util.Map;
public class BillDetailModule extends ModuleEntity {
public BillDetailModule() {
super();
}
public BillDetailModule(Map<String, Object> row) {
super(row);
}
@Override
public String getIdField() {
return "id";
}
}
@@ -0,0 +1,462 @@
package org.example.Entity.System;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.bytedeco.opencv.presets.opencv_core;
import org.example.Entity.Control.Fields.Field;
import org.example.Enums.SystemTypeEnums;
import org.example.Utils.NativeExtensionUtils;
import org.example.Utils.PublicUtil;
import org.example.Utils.SqlAnalyzer;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import static org.example.Utils.DataTableUtil.*;
public class BillModule extends ModuleBaseEntity {
@JsonIgnore
public Map<String, Object> _row;
@JsonProperty("ModuleType")
public int ModuleType = 1;
@JsonIgnore
public int AuditFlag;
@JsonIgnore
public String DetailGuid;
@JsonIgnore
public String ComfirmRemark;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("Main")
public List<Field> Main;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("Detail")
public Object Detail;
public BillModule() {
super();
}
public BillModule(Map<String, Object> row) {
super(row);
this._row = row;
}
private String _detailKey;
@JsonIgnore
@JsonProperty("DetailKey")
public String getDetailKey() {
return (String) get(this._row, "DetailKey", _detailKey);
}
public void setDetailKey(String detailKey) {
this._detailKey = detailKey;
}
private String _redMenuName;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("RedMenuName")
public String getRedMenuName() {
if (_redMenuName == null) {
_redMenuName = (String) get(this._row, "RedMenuName", _redMenuName);
}
return _redMenuName;
}
public void setRedMenuName(String redMenuName) {
this._redMenuName = redMenuName;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("HasSource")
public Boolean HasSource;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("SourceTab")
public List<Map<String, Object>> SourceTab;
private String _billSourceIds;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("BillSourceIds")
public String getBillSourceIds() {
// if (_billSourceIds == null) {
// _billSourceIds = (String) get(this._row, "BillSourceIds", null,null);
// }
_billSourceIds = (_billSourceIds != null) ?
_billSourceIds : (get(_row, "BillSourceIds", null, null) instanceof String) ?
(String) get(_row, "BillSourceIds", null, null) : null;
return _billSourceIds;
}
public void setBillSourceIds(String billSourceIds) {
this._billSourceIds = billSourceIds;
}
private String IdField;
@JsonProperty("IdField")
public String getIdField() {
// return IdField != null ? IdField : getMenuPrefix() + "billdocument_id";
return Optional.ofNullable(super.getIdField())
.filter(id -> !id.trim().isEmpty()) // 处理空字符串(如""、" "
.orElse(getMenuPrefix() + "billdocument_id");
}
public void setIdField(String idField) {
IdField = idField;
}
private String _masterTab;
@JsonIgnore
@JsonProperty("MasterTable")
public String getMasterTable() {
return (String) get(_row, "MasterTable", _masterTab);
}
public void setMasterTable(String masterTable) {
this._masterTab = masterTable;
}
private String _masterSql;
@JsonIgnore
@JsonProperty("MasterSql")
public String getMasterSql() {
_masterSql = (String) get(_row, "MasterSql", _masterSql);
if (_masterSql != null && !_masterSql.isEmpty() && getOtherCond() != null && !getOtherCond().isEmpty()) {
Map<String, String> con = new HashMap<>();
con.put("$other", getOtherCond());
return new SqlAnalyzer(_masterSql).InsertWhere(con, false, false, false);
}
return _masterSql;
}
public void setMasterSql(String masterSql) {
this._masterSql = masterSql;
}
private String _detailTable;
@JsonIgnore
@JsonProperty("DetailTable")
public String getDetailTable() {
return (String) get(_row, "DetailTable", _detailTable);
}
public void setDetailTable(String detailTable) {
this._detailTable = detailTable;
}
private String _detailSql;
@JsonIgnore
@JsonProperty("DetailSql")
public String getDetailSql() {
String value = getStringValue(_row, "DetailSQL", _detailSql, null);
return (value instanceof String) ? (String) value : null;
}
public void setDetailSql(String detailSql) {
this._detailSql = detailSql;
}
private String _scanSql;
@JsonIgnore
@JsonProperty("ScanSql")
public String getScanSql() {
return (String) get(_row, "ScanSql", _scanSql);
}
public void setScanSql(String scanSql) {
this._scanSql = scanSql;
}
private Integer _leftWidth;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("LeftWidth")
public Integer getLeftWidth() {
return (Integer) get(_row, "LeftWidth", _leftWidth);
}
public void setLeftWidth(Integer leftWidth) {
this._leftWidth = leftWidth;
}
private Integer _topHeight;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("TopHeight")
public Integer getTopHeight() {
return (Integer) get(_row, "TopHeight", _topHeight);
}
public void setTopHeight(Integer topHeight) {
this._topHeight = topHeight;
}
private String _updateCond;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("UpdateCond")
public String getUpdateCond() {
if (!OperAble) {
return "1<>1";
}
if (_updateCond != null && !_updateCond.isEmpty()) {
return _updateCond;
}
_updateCond = (String) get(_row, "UpdateCond", _updateCond);
_updateCond = PublicUtil.ReqSqlPmsByRow(null, null, PublicUtil.SqlToCode(_updateCond), SystemTypeEnums.PmType.ignorenull);
if (_updateCond != null && _updateCond.indexOf("{") < 0) {
if (_updateCond.isEmpty()) {
_updateCond = "1==1";
}
}
return _updateCond;
}
public void setUpdateCond(String updateCond) {
this._updateCond = updateCond;
}
private String _otherCond;
@JsonIgnore
@JsonProperty("OtherCond")
public String getOtherCond() {
return (String) get(_row, "OtherCond", _otherCond);
}
public void setOtherCond(String otherCond) {
this._otherCond = otherCond;
}
private String _printFile;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("PrintFile")
public String getPrintFile() {
return (String) get(_row, "PrintFile", _printFile);
}
public void setPrintFile(String printFile) {
this._printFile = printFile;
}
private Integer _printType;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("PrintType")
public Integer getPrintType() {
return (Integer) get(_row, "PrintType", _printType);
}
public void setPrintType(Integer printType) {
this._printType = printType;
}
private String _printSql;
@JsonIgnore
@JsonProperty("PrintSql")
public String getPrintSql() {
return (String) get(_row, "PrintSQL", _printSql);
}
public void setPrintSql(String printSql) {
this._printSql = printSql;
}
private String _printSql2;
@JsonIgnore
public String getPrintSql2() {
return (String) get(_row, "PrintSQL2", _printSql2);
}
public void setPrintSql2(String printSql2) {
this._printSql2 = printSql2;
}
private String _printSql3;
@JsonIgnore
public String getPrintSql3() {
return (String) get(_row, "PrintSQL3", _printSql3);
}
public void setPrintSql3(String printSql3) {
this._printSql3 = printSql3;
}
private Integer _billFlag;
@JsonProperty("BillFlag")
public Integer getBillFlag() {
if (_billFlag == null) {
_billFlag = (Integer) get(_row, "BillFlag", 0);
}
return _billFlag;
}
public void setBillFlag(Integer billFlag) {
this._billFlag = billFlag;
}
@JsonProperty("RedBill")
public Integer getRedBill() {
return NativeExtensionUtils.parseInt(get(_row, "redbill", 0) + "");
}
private Boolean _emptyDetailFlag;
@JsonIgnore
public Boolean getEmptyDetailSaveAble() {
return toBoolean(get(_row, "EmptyDetailFlag", _emptyDetailFlag, false));
}
public void setEmptyDetailSaveAble(Boolean emptyDetailSaveAble) {
this._emptyDetailFlag = emptyDetailSaveAble;
}
private String _detailPrefix;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("DetailPrefix")
public String getDetailPrefix() {
String prefix = (String) get(_row, "detailprefix", _detailPrefix);
if (prefix != null && !prefix.isEmpty()) {
_detailPrefix = prefix.toLowerCase();
}
return _detailPrefix;
}
public void setDetailPrefix(String detailPrefix) {
this._detailPrefix = detailPrefix;
}
private String _billSeq;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("BillSeq")
public String getBillSeq() {
return (String) get(_row, "billseq", _billSeq);
}
public void setBillSeq(String billSeq) {
this._billSeq = billSeq;
}
private String _typeCode;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("TypeCode")
public String getTypeCode() {
return (String) get(_row, "MenuCode", _typeCode);
}
public void setTypeCode(String typeCode) {
this._typeCode = typeCode;
}
private Boolean _emptyRow;
@JsonProperty("EmptyRow")
public Boolean getEmptyRow() {
if (_emptyRow == null) {
_emptyRow = toBoolean(get(_row, "addEmptyRow", _emptyRow, false));
}
return _emptyRow;
}
public void setEmptyRow(Boolean emptyRow) {
this._emptyRow = emptyRow;
}
@JsonProperty("CopyAble")
public Boolean getCopyAble() {
return getAddCopyAble();
}
private String _printCond;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("PrintCond")
public String getPrintCond() {
return (String) get(_row, "PrintCond", _printCond);
}
public void setPrintCond(String printCond) {
this._printCond = printCond;
}
@JsonIgnore
public int Rtagid;
public Integer _comfirmFlag;
@JsonIgnore
public Integer getComfirmFlag() {
if (_comfirmFlag == null) {
_comfirmFlag = (Integer) get(_row, "ComfirmFlag", null);
}
return _comfirmFlag;
}
public void setComfirmFlag(Integer comfirmFlag) {
this._comfirmFlag = comfirmFlag;
}
private String _popupUnionCode;
@JsonProperty("PopupUnionCode")
public String getPopupUnionCode() {
return (String) get(_row, "PopupUnionCode", _popupUnionCode, null);
}
public void setPopupUnionCode(String popupUnionCode) {
this._popupUnionCode = popupUnionCode;
}
@JsonProperty("PopupFields")
public List<Map<String, Object>> PopupFields;
}
@@ -0,0 +1,71 @@
package org.example.Entity.System;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
public class BillReferEntity {
//override
public String Fromkey;
@JsonIgnore
public String DataSql;
private String _mainkey;
@JsonIgnore
public String Mainkey;//++
private String _detailKey;
@JsonIgnore
public String DetailKey;//++
private String _unionKey;
@JsonIgnore
public String UnionKey;//++
private String _condKey;
@JsonIgnore
public String CondKey;//++
private String _sourceName;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String Text;//++
private Integer _sourceType;
public Integer SourceType;//++
private Integer _orderId;
public Integer OrderId;//++
private String _sourceKeyField;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String valueField;//++
private String _sourceCaptionField;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String displayField;//++
private String _sourceSql;
@JsonIgnore
public String SourceSql;//++
private String _sourceDetailSql;
@JsonIgnore
public String DetailSql;//++
private String _unionSql;
@JsonIgnore
public String UnionSql;//++
private String _unionCaption;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String UnionCaption;//++
private String _detailCond;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String DetailCond;//++
private String _detailCondTipMsg;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String DetailCondTipMsg;//++
private String _quickCaption;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String QuickCaption;//++
private String _quickSql;
@JsonIgnore
public String QuickSql;//++
private String _quickTipMsg;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String QuickTipMsg;//++
private String _detailCondField;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String DetailCondField;//++
}
@@ -0,0 +1,219 @@
package org.example.Entity.System;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Base.Component;
import org.example.Enums.SystemTypeEnums;
import org.example.Utils.PublicUtil;
import java.util.Map;
import static org.example.Utils.DataTableUtil.get;
import static org.example.Utils.NativeExtensionUtils.ToInt32;
public class BillSourceModule {
protected Map<String, Object> _row;
public BillSourceModule() {
}
public BillSourceModule(Map<String, Object> row) {
this._row = row;
}
private Integer _sourceId;
@JsonProperty("SourceId")
public int getSourceId() {
return ToInt32(get(_row, "id", _sourceId, null));
}
public void setSourceId(int sourceId) {
this._sourceId = sourceId;
}
private String moduleId;
@JsonProperty("ModuleId")
public String getModuleId() {
return moduleId;
}
public void setModuleId(String moduleId) {
this.moduleId = moduleId;
}
private String _idField;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("IdField")
public String getIdField() {
_idField = (String) get(_row, "sourcekeyfield", _idField, null);
if (_idField != null && !_idField.isEmpty()) {
return _idField.toLowerCase();
}
return _idField;
}
public void setIdField(String idField) {
this._idField = idField;
}
private String _displayField;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("DisplayField")
public String getDisplayField() {
_displayField = (String) get(_row, "sourceresult", _displayField, null);
if (_displayField != null && !_displayField.isEmpty()) {
return _displayField.toLowerCase();
}
return _displayField;
}
public void setDisplayField(String displayField) {
this._displayField = displayField;
}
private String _title;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("Title")
public String getTitle() {
return (String) get(_row, "username", _title, null);
}
public void setTitle(String title) {
this._title = title;
}
private int _sourceType;
@JsonProperty("SourceType")
public int getSourceType() {
return ToInt32(get(_row, "sourcetype", 0));
}
public void setSourceType(int sourceType) {
this._sourceType = sourceType;
}
private String _masterSql;
@JsonIgnore
@JsonProperty("MasterSql")
public String getMasterSql() {
return (String) get(_row, "sourcesql", _masterSql, null);
}
public void setMasterSql(String masterSql) {
this._masterSql = masterSql;
}
private String _detailSql;
@JsonIgnore
@JsonProperty("DetailSql")
public String getDetailSql() {
return (String) get(_row, "detailsql", _detailSql, null);
}
public void setDetailSql(String detailSql) {
this._detailSql = detailSql;
}
private String _detailEnableCond;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("DetailEnableCond")
public String getDetailEnableCond() {
if (_detailEnableCond == null) {
_detailEnableCond = (String) get(_row, "DetailEnableCond", _detailEnableCond, null);
}
_detailEnableCond = PublicUtil.ReqSqlPmsByRow(
null,
null,
PublicUtil.SqlToCode(_detailEnableCond),
SystemTypeEnums.PmType.ignorenull
);
return _detailEnableCond;
}
public void setDetailEnableCond(String detailEnableCond) {
this._detailEnableCond = detailEnableCond;
}
private String _detailEnableMsg;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("DetailEnableMsg")
public String getDetailEnableMsg() {
return (String) get(_row, "DetailEnableMsg", _detailEnableMsg, null);
}
public void setDetailEnableMsg(String detailEnableMsg) {
this._detailEnableMsg = detailEnableMsg;
}
private String _fromkey;
@JsonIgnore
@JsonProperty("Fromkey")
public String getFromkey() {
Object fk = get(_row, "fromkey", _fromkey, null);
if (fk != null && !String.valueOf(fk).isEmpty()) {
_fromkey = String.valueOf(fk);
return _fromkey;
}
return null;
}
public void setFromkey(String fromkey) {
this._fromkey = fromkey;
}
private Object tbarItems;
@JsonProperty("TbarItems")
public Object getTbarItems() {
return tbarItems;
}
public void setTbarItems(Object tbarItems) {
this.tbarItems = tbarItems;
}
/**
* 基础档案右边结构
*/
private Component main;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("Main")
public Component getMain() {
return main;
}
public void setMain(Component main) {
this.main = main;
}
/**
* 明细
*/
private Object details;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("Details")
public Object getDetails() {
return details;
}
public void setDetails(Object details) {
this.details = details;
}
}
@@ -0,0 +1,49 @@
package org.example.Entity.System;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class BillStateEn {
public String billid;
public Integer billstate;
public Integer StepId;
@JsonIgnore
public Integer BillType;
@JsonIgnore
public String StepCode;
@JsonIgnore
public String NextStepCode;
@JsonIgnore
public String BackStepCode;
@JsonIgnore
public Boolean ViewAble;
@JsonIgnore
public Boolean OperAble;
public String Direction;
public String Remark;
public Boolean IsBack;
public Boolean Canceled;
public Boolean Finished;
public Boolean StepClosed;
private int _selectConfirmFlag = 0;
/// <summary>
/// @selectConfirmFlag默认0,用于确认步骤选择(第一次审核传入0,传1代表用户选择后确认);
/// </summary>
public int getSelectConfirmFlag() {
return _selectConfirmFlag;
}
public void setSelectConfirmFlag(int value) {
_selectConfirmFlag = value;
}
public String nextSelectStepCode;
/// <summary>
/// @nextSelectStepOper,需要选择的人员列表,含多个步骤的人员列表,如果@selectConfirmFlag=0作为输出参数使用,代表需要选择的人员,为1则代表用户选择后的人员列表,作为输入参数使用,多步骤之间的人员以分号分隔;
/// </summary>
public String nextSelectStepOper;
public String comfirmOpers;
public int comfirmFlag;
}
@@ -0,0 +1,304 @@
package org.example.Entity.System;
import org.example.Utils.NativeExtensionUtils;
import org.example.Utils.PublicUtil;
import org.example.Utils.WebConfigUtil_web;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.example.Utils.NativeExtensionUtils.dmToBoolean;
import static org.example.Utils.NativeExtensionUtils.toBoolean;
public class FieldModel {
private NamedParameterJdbcTemplate jdbcTemplate;
// 数据库操作器(通过构造注入)
public void setJdbcTemplate(NamedParameterJdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public boolean IsNullAble;
public Class<?> ctype;
public int dbType;
public String databaseType;
public String getDatabaseType(){
return databaseType = WebConfigUtil_web.get("custom.database.type");
}
// 获取数据库参数对象
public SqlParameter getPm() {
if (pmFiledValue == null) {
return new SqlParameter("@" + FiledName, Types.VARCHAR);
}
// 根据实际类型设置SQL类型
int sqlType = getSqlTypeByClass(ctype);
return new SqlParameter("@" + FiledName, sqlType);
}
public String getPmName() {
return String.format("@%s", FiledName);
}
public String FiledName;
public String FiledLabel;
public boolean hasSpecVal = false;
private Object _filedvalue;
private static final String[] KEY_WORDS = {"'", "<"};
private static final Pattern REGEX_SQL_KEYWORD = Pattern.compile(
"\\b(SELECT|UPDATE|DELETE|INSERT|FROM|WHERE|AND|OR|NOT|IN|LIKE|AS|CREATE|ALTER|DROP|TRUNCATE|CASCADE|COALESCE|IF|EXISTS|GRANT|REVOKE|LOCK|UNION|ALL|ANY|SOME|INTERSECT|EXCEPT)\\b",
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE
);
private static boolean hasKeyWords(String input) {
if (input == null) return false;
for (String word : KEY_WORDS) {
if (input.contains(word)) return true;
}
return REGEX_SQL_KEYWORD.matcher(input).find() || input.startsWith("data:");
}
public boolean TrimSpec;
public int FieldLength;
public boolean validLength(int[] valueLen) {
valueLen[0] = 0;
if (ctype == String.class) {
String value = (getFiledValue() + "").trim(); // 移除trim()方法的参数
// 如果需要根据trimSpec处理不同的修剪逻辑,可以分情况处理
if (TrimSpec) {
value = value.replace("'", ""); // 移除单引号
} else {
value = value.trim(); // 修剪空格
}
valueLen[0] = getStringLen(value);
return valueLen[0] <= FieldLength;
}
return true;
}
public String ValidMsg;
public static int getStringLen(String text) {
if (text == null) return 0;
byte[] bytes = text.getBytes(StandardCharsets.US_ASCII);
int length = 0;
for (byte b : bytes) {
// ASCII码63对应'?',表示非ASCII字符
length += (b == 63) ? 2 : 1;
}
return length;
}
public Object SqlFieldVal;
public Object pmFiledValue;
// 设置字段值(核心逻辑)
public void setFiledValue(Object value) {
_filedvalue = value;
// System.out.println("字段名:" + FiledName + "ctype类型:" + (ctype != null ? ctype.getName() : "null"));
// 检查是否为空
if (isStringNullOrEmpty(objectToString(_filedvalue))) {
_filedvalue = PublicUtil.GetSqlDefaultValByType(ctype, IsNullAble);
pmFiledValue = _filedvalue;
SqlFieldVal = _filedvalue;
return;
}
// 处理big int类型的特殊情况
String filedStr = objectToString(_filedvalue);
if (filedStr.startsWith("0E-")) {
_filedvalue = 0;
pmFiledValue = _filedvalue;
SqlFieldVal = _filedvalue;
return;
}
// 处理列表类型
if (_filedvalue instanceof List<?>) {
_filedvalue = sJoin((List<?>) _filedvalue);
}
// 处理字符串修剪
String tempValue = objectToString(_filedvalue).trim();
_filedvalue = tempValue;
if (TrimSpec && tempValue.startsWith("'") && tempValue.endsWith("'")) {
_filedvalue = tempValue.substring(1, tempValue.length() - 1);
}
if (!isStringNullOrEmpty(objectToString(_filedvalue))) {
// 处理数值类型
if (ctype == int.class || ctype == Integer.class ||
ctype == float.class || ctype == Float.class ||
ctype == double.class || ctype == Double.class ||
ctype == BigDecimal.class ||
ctype == long.class || ctype == Long.class)
{
String valueStr = objectToString(_filedvalue).trim();
if (valueStr.indexOf('E') > -1 || valueStr.indexOf('e') > -1) {
Pattern pattern = Pattern.compile("[^\\d\\.\\-Ee]");
Matcher matcher = pattern.matcher(valueStr);
if (!matcher.find()) {
try {
_filedvalue = new BigDecimal(valueStr);
} catch (NumberFormatException e) {
handleInvalidNumberFormat(valueStr);
}
} else {
handleInvalidNumberFormat(valueStr);
}
} else {
Pattern pattern = Pattern.compile("[^\\d\\.\\-\\,]");
Matcher matcher = pattern.matcher(valueStr);
if (matcher.find() || "-".equals(valueStr) || ".".equals(valueStr)) {
if ("true".equalsIgnoreCase(valueStr) || "false".equalsIgnoreCase(valueStr)) {
_filedvalue = "true".equalsIgnoreCase(valueStr) ? 1 : 0;
} else {
ValidMsg = String.format("字段%s输入字符串类型不正确,输入值为%s,应该为%s类型!",
FiledName, _filedvalue, ctype.getName());
_filedvalue = 0;
}
} else {
try {
_filedvalue = new BigDecimal(valueStr.replace(",", ""));
} catch (NumberFormatException e) {
handleInvalidNumberFormat(valueStr);
}
}
}
}
// 处理日期类型
else if (ctype == Date.class && !(value instanceof Date)) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
try {
Date dvalue = sdf.parse(objectToString(value));
_filedvalue = sdf.format(dvalue);
} catch (ParseException e) {
ValidMsg = String.format("字段%s输入时间类型值格式不正确,输入值为%s,应该为标准时间类型!",
FiledName, _filedvalue);
}
}
// 处理布尔类型
else if (ctype == boolean.class || ctype == Boolean.class) {
if (getDatabaseType().equals("dm")) _filedvalue = dmToBoolean(Objects.toString(_filedvalue));
else _filedvalue = toBoolean(_filedvalue);
}
// 处理字符串类型
else if (ctype == String.class) {
String valueStr = objectToString(_filedvalue);
int vLen = valueStr.length();
if (hasKeyWords(valueStr)) {
Pattern pattern = Pattern.compile("\"");
Matcher matcher = pattern.matcher(valueStr);
vLen += matcher.groupCount();
}
if (FieldLength > 0 && vLen > FieldLength) {
int subLength = Math.min(FieldLength, valueStr.length());
_filedvalue = valueStr.substring(0, subLength);
ValidMsg = String.format("字段%s输入字符串长度过长,应该在%s个字符范围内!现有长度%s!",
FiledName, FieldLength, vLen);
}
}
pmFiledValue = _filedvalue;
SqlFieldVal = _filedvalue;
// if (hasKeyWords(objectToString(_filedvalue))) {
// hasSpecVal = true;
// _filedvalue = "";
// }
// SqlFieldVal = _filedvalue;
// 处理数据库类型
if (dbType == 231) { // nvarchar
SqlFieldVal = String.format("N'%s'", escapeSql(objectToString(SqlFieldVal)));
} else {
SqlFieldVal = String.format("'%s'", escapeSql(objectToString(SqlFieldVal)));
}
} else {
_filedvalue = PublicUtil.GetSqlDefaultValByType(ctype, IsNullAble);
pmFiledValue = _filedvalue;
SqlFieldVal = _filedvalue;
}
}
// 辅助方法:处理无效的数字格式
private void handleInvalidNumberFormat(String valueStr) {
if ("true".equalsIgnoreCase(valueStr) || "false".equalsIgnoreCase(valueStr)) {
_filedvalue = "true".equalsIgnoreCase(valueStr) ? 1 : 0;
} else {
ValidMsg = String.format("字段%s输入字符串类型不正确,输入值为%s,应该为%s类型!",
FiledName, _filedvalue, ctype.getName());
_filedvalue = 0;
}
}
// 辅助方法:SQL转义
private String escapeSql(String str) {
if (str == null) {
return "";
}
return str.replace("'", "''");
}
// 辅助方法:将对象转换为字符串
private String objectToString(Object obj) {
if (obj == null) {
return "";
}
return obj.toString();
}
// 辅助方法:检查字符串是否为空
private boolean isStringNullOrEmpty(String str) {
return str == null || str.trim().isEmpty();
}
// 辅助方法:List转换为字符串
private String sJoin(List<?> list) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.size(); i++) {
if (i > 0) {
sb.append(",");
}
sb.append(objectToString(list.get(i)));
}
return sb.toString();
}
public Object getFiledValue() {
return _filedvalue;
}
// 辅助方法:根据Java类型获取SQL类型
private int getSqlTypeByClass(Class<?> type) {
if (type == Integer.class) return Types.INTEGER;
if (type == Long.class) return Types.BIGINT;
if (type == String.class) return Types.VARCHAR;
if (type == Date.class) return Types.DATE;
if (type == Timestamp.class) return Types.TIMESTAMP;
if (type == Boolean.class) return Types.BOOLEAN;
if (type == BigDecimal.class) return Types.DECIMAL;
return Types.VARCHAR;
}
}
@@ -0,0 +1,291 @@
package org.example.Entity.System;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Utils.DataTableUtil;
import org.example.Utils.DateTimeUtil;
import org.example.Utils.NativeExtensionUtils;
import java.util.*;
public class FlowStepInfo extends RowBase {
protected Map<String, Object>[] _his;
public FlowStepInfo(Map<String, Object> row, Map<String, Object>[] his) {
super(row);
this._his = his;
}
public int getId() {
return NativeExtensionUtils.ToInt32(DataTableUtil.get(row, "id", 0));
}
@JsonProperty("StepName")
public String getStepName() {
String value = DataTableUtil.get(row, "stepName", "") + "";
return value.trim().replace("\n", "");
}
@JsonProperty("stepName")
public String getStepNameWithHisInfo() {
if (getHisRec() != null) {
Map<String, Object> hisRec = getHisRec();
Date happenTime = NativeExtensionUtils.toDateTime(hisRec.get("happentime"));
Date operTime = NativeExtensionUtils.toDateTime(hisRec.get("opertime"));
String difDate = DateTimeUtil.getDateDiff(happenTime, operTime);
String hisInfo = "(" + hisRec.get("operatorname") + ")→" +
(NativeExtensionUtils.isNullOrEmpty(difDate) ? "秒速通过" : difDate) + "\n" +
(hisRec.get("opertime") + "").replace(" ", "\t");
return getStepName() + "\n" + hisInfo;
}
return getStepName();
}
@JsonProperty("stepCode")
public int getStepCode() {
return NativeExtensionUtils.ToInt32(DataTableUtil.get(row, "stepcode", 0));
}
private Integer _stepOver;
@JsonProperty("stepOver")
public int getStepOver() {
if (_stepOver == null) {
_stepOver = NativeExtensionUtils.ToInt32(DataTableUtil.get(row, "stepover", 0));
}
return _stepOver;
}
public void setStepOver(int value) {
_stepOver = value;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("operUser")
public String getOperUser() {
String user = DataTableUtil.get(row, "operUser", "") + "";
if (!NativeExtensionUtils.isNullOrEmpty(user)) {
// 使用String.replaceAll()替代trim(','),移除首尾的逗号
return user.replaceAll("^,+,", "").replaceAll(",+$", "");
}
return null;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("viewUser")
public String getViewUser() {
return DataTableUtil.get(row, "viewUser", "") + "";
}
private Boolean _mulitAudit;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("multiAudit")
public Boolean getMultiAudit() {
if (_mulitAudit == null) {
_mulitAudit = NativeExtensionUtils.toBoolean(DataTableUtil.get(row, "multiAudit", false));
}
return _mulitAudit ? _mulitAudit : null;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("stepTime")
public Object getStepTime() {
return DataTableUtil.get(row, "stepTime", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("AffirmBak")
public Object getAffirmBak() {
return DataTableUtil.get(row, "AffirmBak", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("flowcharTagId")
public Object getFlowcharTagId() {
return DataTableUtil.get(row, "flowcharTagId", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("flowcharWidth")
public Object getFlowcharWidth() {
return DataTableUtil.get(row, "flowcharWidth", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("flowcharHeght")
public Object getFlowcharHeght() {
return DataTableUtil.get(row, "flowcharHeght", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("FlowCharfillcolor")
public Object getFlowCharfillcolor() {
return DataTableUtil.get(row, "FlowCharfillcolor", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("LeftFlowCharfillcolor")
public Object getLeftFlowCharfillcolor() {
return DataTableUtil.get(row, "LeftFlowCharfillcolor", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("LeftFlowCharWidth")
public Object getLeftFlowCharWidth() {
return DataTableUtil.get(row, "LeftFlowCharWidth", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("fontSize")
public Object getFontSize() {
return DataTableUtil.get(row, "fontSize", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("fontColor")
public Object getFontColor() {
return DataTableUtil.get(row, "fontColor", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("LeftFlowCharTagId")
public Object getLeftFlowCharTagId() {
return DataTableUtil.get(row, "LeftFlowCharTagId", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("fontWeight")
public Object getFontWeight() {
return DataTableUtil.get(row, "fontWeight", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("fontFamily")
public Object getFontFamily() {
return DataTableUtil.get(row, "fontFamily", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("LeftFontFamily")
public Object getLeftFontFamily() {
return DataTableUtil.get(row, "LeftFontFamily", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("LeftFontSize")
public Object getLeftFontSize() {
return DataTableUtil.get(row, "LeftFontSize", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("LeftFontColor")
public Object getLeftFontColor() {
return DataTableUtil.get(row, "LeftFontColor", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("LeftFontWeight")
public Object getLeftFontWeight() {
return DataTableUtil.get(row, "LeftFontWeight", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("LeftFlowCharHeight")
public Object getLeftFlowCharHeight() {
return DataTableUtil.get(row, "LeftFlowCharHeight", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("FlowCharScale")
public Object getFlowCharScale() {
return DataTableUtil.get(row, "FlowCharScale", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("flowcharLineHeght")
public Object getFlowcharLineHeght() {
return DataTableUtil.get(row, "flowcharLineHeght", null);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("HisRec")
public Map<String, Object> getHisRec() {
if (_his == null || _his.length == 0) {
return null;
}
Map<String, Object> hisTab = _his[_his.length - 1];
if (hisTab != null && _his.length > 1) {
List<String> operatorIds = new ArrayList<>();
List<String> operatorNames = new ArrayList<>();
List<String> operAdvices = new ArrayList<>();
for (Map<String, Object> row : _his) {
operatorIds.add(row.get("operatorid") + "");
operatorNames.add(row.get("operatorname") + "");
operAdvices.add(row.get("operatorname") + "" + row.get("operAdvice"));
}
hisTab.put("operatorid", String.join(",", operatorIds));
hisTab.put("operatorname", String.join(",", operatorNames));
hisTab.put("operAdvice", String.join("</br>", operAdvices));
}
return hisTab;
}
@JsonIgnore
public String getNextSteps() {
return DataTableUtil.get(row, "NextStepCode", "") + "";
}
public void setNextSteps(String value) {
row.put("NextStepCode", value);
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("NextStepCode")
public int[] getNextStepCode() {
String nextSteps = getNextSteps();
if (NativeExtensionUtils.isNullOrEmpty(nextSteps)) {
return null;
}
String[] codeStrs = nextSteps.split(",");
List<Integer> codeList = new ArrayList<>();
for (String codeStr : codeStrs) {
if (!NativeExtensionUtils.isNullOrEmpty(codeStr)) {
codeList.add(NativeExtensionUtils.ToInt32(codeStr));
}
}
if (codeList.isEmpty()) {
return null;
}
int[] codes = new int[codeList.size()];
for (int i = 0; i < codeList.size(); i++) {
codes[i] = codeList.get(i);
}
return codes;
}
}
// 补充必要的基础类定义(假设存在)
abstract class RowBase {
protected Map<String, Object> row;
public RowBase(Map<String, Object> row) {
this.row = row;
}
protected Object GetVal(String key) {
return DataTableUtil.get(row, key, null);
}
protected void SetVal(String key, Object value) {
row.put(key, value);
}
}
@@ -0,0 +1,108 @@
package org.example.Entity.System;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.util.Map;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class LoginUserInfo {
private static final long serialVersionUID = 1L; // 显式添加序列化ID
// 字段保持不变
public String UserId = "0";
public String UserName;
public String UserCode;
public String SeriesId;
public Integer ServerId = 0;
@JsonIgnore
public String DepCode;
@JsonIgnore
public String RoleId;
@JsonIgnore
public String RoleIds;
@JsonIgnore
public String InPwd = "";
//新增
@JsonIgnore
public Boolean IsWeekPwd;
@JsonIgnore
public String PurviewStr;
@JsonIgnore
public String Pwd;
@JsonIgnore
public String ConnectionString;
@JsonIgnore
public String ProviderName;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("Other")
public Map<String, Object> Other;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("AppIndex")
public String AppIndex;
@JsonIgnore
public Object AttacInfo;
@JsonIgnore
public Integer LoginType;
public Integer ClientId;
public Integer AttendanceTime;
@JsonIgnore
public Boolean IsClientUser = false;
@JsonIgnore
public String Token;
@JsonIgnore
public String LoginOs;
@JsonIgnore
public Boolean FromToken;
// 1. 添加显式无参构造函数(Jackson 序列化必需)
public LoginUserInfo() {}
// 2. 添加所有非 @JsonIgnore 字段的 getter 方法(Jackson 读取字段用)
public String getUserId() {
return UserId;
}
public String getUserName() {
return UserName;
}
public String getUserCode() {
return UserCode;
}
public String getSeriesId() {
return SeriesId;
}
public Integer getServerId() {
return ServerId;
}
public Map<String, Object> getOther() {
return Other;
}
public String getAppIndex() {
return AppIndex;
}
public Integer getClientId() {
return ClientId;
}
public Integer getAttendanceTime() {
return AttendanceTime;
}
// 3. 保留原有的 getRoleIds 方法(无需修改)
@JsonIgnore
public String[] getRoleIds() {
if (RoleId == null) {
return new String[0];
}
return RoleId.split(",");
}
}
@@ -0,0 +1,366 @@
package org.example.Entity.System;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Enums.SystemTypeEnums;
import org.example.Utils.DataTableUtil;
import org.example.Utils.PublicUtil;
import org.example.Utils.NativeExtensionUtils;
import java.util.Map;
/**
* 移动端卡片实体类
* 创建时间:2020-07-22 18:07:38
*/
public class MobileCard {
private Map<String, Object> row;
// 构造方法
public MobileCard() {
}
public MobileCard(Map<String, Object> row) {
this();
this.row = row;
}
// 分组名称
private String groupName;
@JsonIgnore
public String getGroupName() {
if (groupName == null) {
groupName = DataTableUtil.getStringValue(row, "groupname", "");
}
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
// 列名
private String colName;
@JsonIgnore
public String getColName() {
if (colName == null) {
colName = DataTableUtil.getStringValue(row, "colname", "");
}
return colName;
}
public void setColName(String colName) {
this.colName = colName;
}
// 分组可见性
private String groupVisible;
@JsonIgnore
public boolean isGroupVisible() {
if (groupVisible == null) {
groupVisible = DataTableUtil.getStringValue(row, "groupvisible", "");
}
return !"0".equals(groupVisible);
}
// 分组详情
private String groupDetail;
@JsonIgnore
public String getGroupDetail() {
if (groupDetail == null) {
groupDetail = DataTableUtil.getStringValue(row, "groupdetail", "");
}
return groupDetail;
}
// 行号
private Integer rowId;
@JsonProperty("RowId")
public int getRowId() {
if (rowId == null) {
rowId = NativeExtensionUtils.ToInt32(DataTableUtil.getStringValue(row, "rowid", ""));
}
return rowId;
}
public void setRowId(int rowId) {
this.rowId = rowId;
}
private Integer _colId;
@JsonProperty("ColId")
public int getColId() {
return (int) ( NativeExtensionUtils.ToInt32(DataTableUtil.getStringValue(row, "colid", "")));
}
public void setColId(int _colId) {
this._colId = _colId;
}
// 明细ID
private Integer mxId;
@JsonIgnore
public int getMxId() {
if (mxId == null) {
mxId = NativeExtensionUtils.ToInt32(DataTableUtil.getStringValue(row, "mxid", ""));
}
return mxId;
}
public void setMxId(int mxId) {
this.mxId = mxId;
}
// 行高
private Integer rowHeight;
@JsonProperty("RowHeight")
public int getRowHeight() {
if (rowHeight == null) {
rowHeight = NativeExtensionUtils.ToInt32(DataTableUtil.getStringValue(row, "rowheight", ""));
}
return rowHeight;
}
public void setRowHeight(int rowHeight) {
this.rowHeight = rowHeight;
}
// 宽度
private String width;
@JsonProperty("width")
public String getWidth() {
if (width == null) {
width = DataTableUtil.getStringValue(row, "width", "");
}
return width;
}
public void setWidth(String width) {
this.width = width;
}
// 下边线
private Boolean splitLine;
@JsonProperty("SplitLine")
public boolean isSplitLine() {
if (splitLine == null) {
splitLine = NativeExtensionUtils.toBoolean(DataTableUtil.getStringValue(row, "splitline", "0"));
}
return splitLine;
}
public void setSplitLine(boolean splitLine) {
this.splitLine = splitLine;
}
// 行内容
private String displayText;
@JsonProperty("Content")
public String getContent() {
if (displayText == null) {
displayText = DataTableUtil.getStringValue(row, "displaytext", "");
}
return displayText;
}
public void setContent(String content) {
this.displayText = content;
}
// 字体
private String fontFamilyt;
@JsonProperty("FontFamily")
public String getFontFamily() {
if (fontFamilyt == null) {
fontFamilyt = DataTableUtil.getStringValue(row, "fontname", "");
}
return fontFamilyt;
}
public void setFontFamily(String fontFamily) {
this.fontFamilyt = fontFamily;
}
// 字体大小
private Integer fontSize;
@JsonProperty("FontSize")
public int getFontSize() {
if (fontSize == null) {
fontSize = NativeExtensionUtils.ToInt32(DataTableUtil.getStringValue(row, "fontsize", ""));
}
return fontSize;
}
public void setFontSize(int fontSize) {
this.fontSize = fontSize;
}
// 字体颜色
private String fColor;
@JsonProperty("FColor")
public String getFColor() {
if (fColor == null) {
fColor = DataTableUtil.getStringValue(row, "fcolor", "");
}
return fColor;
}
public void setFColor(String fColor) {
this.fColor = fColor;
}
// 背景颜色
private String bgColor;
@JsonProperty("BgColor")
public String getBgColor() {
if (bgColor == null) {
bgColor = DataTableUtil.getStringValue(row, "bcolor", "");
}
return bgColor;
}
public void setBgColor(String bgColor) {
this.bgColor = bgColor;
}
// dbColor属性
private String dbColor;
@JsonProperty("DbColor")
public String getDbColor() {
if (dbColor == null) {
dbColor = DataTableUtil.getStringValue(row, "dbcolor", "");
}
return dbColor;
}
public void setDbColor(String dbColor) {
this.dbColor = dbColor;
}
// dfColor属性
private String dfColor;
@JsonProperty("DfColor")
public String getDfColor() {
if (dfColor == null) {
dfColor = DataTableUtil.getStringValue(row, "dfcolor", "");
}
return dfColor;
}
public void setDfColor(String dfColor) {
this.dfColor = dfColor;
}
// 加粗
private Boolean bold;
@JsonProperty("Bold")
public boolean isBold() {
if (bold == null) {
bold = NativeExtensionUtils.toBoolean(DataTableUtil.getStringValue(row, "fbold", "0"));
}
return bold;
}
public void setBold(boolean bold) {
this.bold = bold;
}
// 倾斜
private Boolean fitalic;
@JsonProperty("Fitalic")
public boolean isFitalic() {
if (fitalic == null) {
fitalic = NativeExtensionUtils.toBoolean(DataTableUtil.getStringValue(row, "fitalic", "0"));
}
return fitalic;
}
public void setFitalic(boolean fitalic) {
this.fitalic = fitalic;
}
// 删除线
private Boolean fstrikeline;
@JsonProperty("FStrikeLine")
public boolean isFStrikeLine() {
if (fstrikeline == null) {
fstrikeline = NativeExtensionUtils.toBoolean(DataTableUtil.getStringValue(row, "fstrikeline", "0"));
}
return fstrikeline;
}
public void setFStrikeLine(boolean fstrikeline) {
this.fstrikeline = fstrikeline;
}
// 靠右对齐
private Boolean rightAlign;
@JsonProperty("RightAlign")
public boolean isRightAlign() {
if (rightAlign == null) {
rightAlign = NativeExtensionUtils.toBoolean(DataTableUtil.getStringValue(row, "RightAlign", "0"));
}
return rightAlign;
}
public void setRightAlign(boolean rightAlign) {
this.rightAlign = rightAlign;
}
// 显示类型 --0=普通,1=电话,2=QQ,3=微信,4=网站,5=地图
private Integer displayType;
@JsonProperty("DType")
public int getDType() {
if (displayType == null) {
displayType = NativeExtensionUtils.ToInt32(DataTableUtil.getStringValue(row, "displayType", ""));
}
return displayType;
}
public void setDType(int dType) {
this.displayType = dType;
}
// 显示条件
private String displayCond;
@JsonProperty("Cond")
public String getCond() {
if (displayCond != null) {
return displayCond;
}
displayCond = DataTableUtil.getStringValue(row, "displayCond", null);
if (displayCond != null && !displayCond.isEmpty()) {
displayCond = PublicUtil.ReqSqlPmsByRow(
null,
null,
PublicUtil.SqlToCode(displayCond),
SystemTypeEnums.PmType.ignorenull
);
}
return displayCond;
}
public void setCond(String cond) {
this.displayCond = cond;
}
// 文字居中方式 1,2,3 左,中,右
private Integer align;
@JsonProperty("Align")
public int getAlign() {
if (align == null) {
align = NativeExtensionUtils.ToInt32(DataTableUtil.getStringValue(row, "textAlign", "1"));
}
return align;
}
public void setAlign(int align) {
this.align = align;
}
}
@@ -0,0 +1,503 @@
package org.example.Entity.System;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Com.SysPoPupMenuBtn;
import org.example.Utils.DataTableUtil;
import java.util.ArrayList;
import java.util.Map;
import java.util.Optional;
import static org.example.Utils.DataTableUtil.get;
import static org.example.Utils.NativeExtensionUtils.parseInt;
import static org.example.Utils.NativeExtensionUtils.toBoolean;
import static org.example.Utils.PublicUtil.EvalCond;
import static org.example.Utils.PublicUtil.SqlToCode;
public class ModuleBaseEntity extends ModuleEntity {
public ModuleBaseEntity() {
super();
}
public ModuleBaseEntity(Map<String, Object> basemodule) {
super(basemodule);
}
public Boolean OperAble = true;
private Boolean _applyFlag;
@JsonProperty("ApplyAble")
public Boolean getApplyAble() {
return toBoolean(DataTableUtil.getRowVal(basemodule, "SaveApplyFlag", _applyFlag != null ? _applyFlag : true));
}
public void setApplyAble(Boolean value) {
this._applyFlag = value;
}
private Boolean _backSelected;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("BackSelected")
public Boolean getBackSelected() {
_backSelected = toBoolean(basemodule.getOrDefault("BackSelected", _backSelected));
return _backSelected != null && _backSelected ? _backSelected : null;
}
public void setBackSelected(Boolean value) {
this._backSelected = value;
}
private Boolean _muitlAudit;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("MuitlAudit")
public Boolean getMuitlAudit() {
_muitlAudit = toBoolean(get(basemodule, "MuitlAudit", _muitlAudit));
return _muitlAudit != null && _muitlAudit ? _muitlAudit : null;
}
public void setMuitlAudit(Boolean value) {
this._muitlAudit = value;
}
private Boolean _NoFastAudit;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("NoFastAudit")
public Boolean getNoFastAudit() {
_NoFastAudit = toBoolean(get(basemodule, "disAppFastAudit", _NoFastAudit,null));
return (Boolean) _NoFastAudit ? _NoFastAudit : null;
}
public void setNoFastAudit(Boolean value) {
this._NoFastAudit = value;
}
private String _taskSql;
@JsonIgnore
@JsonProperty("TaskSql")
public String getTaskSql() {
return (String) basemodule.getOrDefault("taskSql", _taskSql);
}
public void setTaskSql(String value) {
this._taskSql = value;
}
private String _countSql;
@JsonIgnore
@JsonProperty("CountSql")
public String getCountSql() {
Object value = basemodule.get("countSql");
return value != null ? (String) value : _countSql;
}
public void setCountSql(String value) {
this._countSql = value;
}
@JsonProperty("NeedCount")
public boolean getNeedCount() {
return getCountSql() != null && !getCountSql().isEmpty();
}
@JsonIgnore
public Boolean CondSelect = true;
private String _overBackCond;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("OverBackCond")
public String getOverBackCond() {
return (String) basemodule.getOrDefault("OverBackCond", _overBackCond);
}
public void setOverBackCond(String value) {
this._overBackCond = value;
}
private String _attatchModifyCond;
@JsonIgnore
@JsonProperty("AttatchModifyCond")
public String getAttatchModifyCond() {
return (String) basemodule.getOrDefault("attatchModifyCond", _attatchModifyCond);
}
public void setAttatchModifyCond(String value) {
this._attatchModifyCond = value;
}
private String _overBackSql;
@JsonIgnore
@JsonProperty("OverBackSql")
public String getOverBackSql() {
return (String) get(basemodule, "OverBackSql", _overBackSql, null);
}
public void setOverBackSql(String value) {
this._overBackSql = value;
}
private String _overBackKey;
@JsonIgnore
@JsonProperty("OverBackKey")
public String getOverBackKey() {
Object value = get(basemodule, "OverBackKey", _overBackKey);
return value != null ? value.toString() : "";
}
public void setOverBackKey(String value) {
this._overBackKey = value;
}
private String _overBackOper;
@JsonIgnore
@JsonProperty("OverBackOper")
public String getOverBackOper() {
return (String) basemodule.getOrDefault("OverBackOper", _overBackOper);
}
public void setOverBackOper(String value) {
this._overBackOper = value;
}
private Boolean _importFlag;
@JsonProperty("ImportAble")
public Boolean getImportAble() {
if (!OperAble) return false;
return _importFlag != null ? _importFlag : toBoolean(basemodule.getOrDefault("ImportFlag", true));
}
public void setImportAble(Boolean value) {
this._importFlag = value;
}
private String _importCond;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ImportCond")
public String getImportCond() {
return (String) basemodule.getOrDefault("ImportCond", _importCond);
}
public void setImportCond(String value) {
this._importCond = value;
}
private String _exportCond;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ExportCond")
public String getExportCond() {
return (String) get(basemodule, "ExportCond", _exportCond, null);
}
public void setExportCond(String value) {
this._exportCond = value;
}
private Boolean _exportFlag;
@JsonProperty("ExportAble")
public Boolean getExportAble() {
if (!OperAble) return false;
Boolean exportAble = _exportFlag != null ? _exportFlag : toBoolean(basemodule.getOrDefault("ExportFlag", true));
if (!exportAble) return false;
if (getExportCond() == null || getExportCond().trim().isEmpty()) {
return exportAble;
} else if (!getExportCond().contains("{")) {
exportAble = toBoolean(EvalCond(SqlToCode(getExportCond()), null, true));
}
_exportFlag = exportAble;
return _exportFlag;
}
public void setExportAble(Boolean value) {
this._exportFlag = value;
}
@JsonIgnore
@JsonProperty("ModuleName")
public String getModuleName() {
boolean[] isUrl = new boolean[1];
return SystemMenu.convertToModuleName((String) basemodule.getOrDefault("dllfilename", null), 0, isUrl);
}
@JsonIgnore
@JsonProperty("AddDllName")
public String getAddDllName() {
return (String) basemodule.getOrDefault("adddllname", null);
}
private String _addXtype;
@JsonProperty("AddXtype")
public String getAddXtype() {
if (_addXtype == null || _addXtype.isEmpty()) {
_addXtype = (String) basemodule.getOrDefault("adddllname", null);
if (_addXtype != null && !_addXtype.isEmpty()) {
_addXtype = _addXtype.trim();
// 这里需要实现 SystemMenu.ConvertToModuleName 对应的 Java 逻辑
boolean[] isUrl = new boolean[1];
_addXtype = SystemMenu.convertToModuleName(_addXtype, 0, isUrl);
}
return _addXtype;
}
return _addXtype;
}
@JsonIgnore
public String ContextMenuId;
@JsonIgnore
public SysPoPupMenuBtn PopBtn;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer BillType;
private String _dirId;
@JsonProperty("DirId")
public String getDirId() {
// return (String) DataTableUtil.get(basemodule, "dirid", _dirId, null);
return Optional.ofNullable(get(basemodule, "dirid", _dirId, null))
.map(Object::toString)
.orElse(null);
}
public void setDirId(String value) {
this._dirId = value;
}
private Integer _editType;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("EditType")
public Integer getEditType() {
return (Integer) basemodule.getOrDefault("editType", _editType);
}
public void setEditType(Integer value) {
this._editType = value;
}
private Boolean _cellTplflag;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("CellTplflag")
public Boolean getCellTplflag() {
Boolean flag = toBoolean(basemodule.getOrDefault("cellTplflag", _cellTplflag));
return flag != null && flag ? flag : null;
}
public void setCellTplflag(Boolean value) {
this._cellTplflag = value;
}
private boolean _cardTplflag;
// 2026.2.24新增
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("WebCardTpl")
public Boolean getWebCardTpl() {
boolean flag = toBoolean(basemodule.getOrDefault("WebCardflag", _cardTplflag));
if (flag) return true;
return false;
}
public void setWebCardTpl(Boolean value) {
this._cardTplflag = value;
}
private String _speciesNo;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("FileSpeciesNo")
public String getFileSpeciesNo() {
return get(basemodule, "FileSpeciesNo", _speciesNo) != null ? (String) get(basemodule, "FileSpeciesNo", _speciesNo) : "";
}
public void setFileSpeciesNo(String value) {
this._speciesNo = value;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("AttcViewType")
public Integer AttcViewType;
private String _ftype;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("FType")
public String getFType() {
_ftype = _ftype != null ? _ftype : (String) basemodule.getOrDefault("ftype", "");
return _ftype != null && !_ftype.isEmpty() ? _ftype : null;
}
public void setFType(String value) {
this._ftype = value;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("CusAddTpl")
public String CusAddTpl;
private String _addHint;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("AddHint")
public String getAddHint() {
Object value = get(basemodule, "addhint", _speciesNo, null);
return value != null ? value.toString() : "";
}
public void setAddHint(String value) {
this._addHint = value;
}
private Integer _rowHeight;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("RowHeight")
public Integer getRowHeight() {
if (_rowHeight == null || _rowHeight == 0) {
Object h = basemodule.getOrDefault("rowHeight", _rowHeight);
if (h != null) {
_rowHeight = Integer.parseInt(h.toString());
}
}
return _rowHeight;
}
public void setRowHeight(Integer value) {
this._rowHeight = value;
}
private Integer _attcLeafOnly;
@JsonProperty("AttcLeafOnly")
public Integer getAttcLeafOnly() {
return _attcLeafOnly != null ? _attcLeafOnly : parseInt(basemodule.getOrDefault("bmpSpecIsMJ", true).toString());
}
public void setAttcLeafOnly(Integer value) {
this._attcLeafOnly = value;
}
private Integer _accInfoWidth;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("AccInfow")
public Integer getAccInfow() {
return (Integer) basemodule.getOrDefault("attInfow", _accInfoWidth);
}
public void setAccInfow(Integer value) {
this._accInfoWidth = value;
}
@JsonProperty("defaultSearch")
public Boolean getDefaultSearch() {
return toBoolean(basemodule.getOrDefault("defaultSearch", true));
}
@JsonIgnore
public Map<String, Object> MasterData;
@JsonIgnore
public ArrayList<Map<String, Object>> DetailData;
@JsonIgnore
@JsonProperty("NewVer")
public Boolean getNewVer() {
return toBoolean(basemodule.getOrDefault("newver", false));
}
@JsonIgnore
@JsonProperty("NewWFVer")
public Boolean getNewWFVer() {
return toBoolean(basemodule.getOrDefault("newwfver", false));
}
private Boolean _addCopyFlag;
@JsonIgnore
public String getAttcField1(){
return basemodule.getOrDefault("attcfield1",false)!=null?basemodule.getOrDefault("attcfield1",false).toString():"";
}
@JsonIgnore
public String getAttcField2(){
return basemodule.getOrDefault("attcfield2",false)!=null?basemodule.getOrDefault("attcfield2",false).toString():"";
}
@JsonIgnore
public String getAttcField3(){
return basemodule.getOrDefault("attcfield3",false)!=null?basemodule.getOrDefault("attcfield3",false).toString():"";
}
@JsonProperty("AddCopyAble")
public Boolean getAddCopyAble() {
return toBoolean(basemodule.getOrDefault("addCopy", _addCopyFlag != null ? _addCopyFlag : true));
}
public void setAddCopyAble(Boolean value) {
this._addCopyFlag = value;
}
private String _desp;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("desp")
public String getDesp() {
Object value = basemodule.getOrDefault("desp", _desp);
return value != null ? value.toString() : "";
}
public void setDesp(String value) {
this._desp = value;
}
private String _noDataMsg;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("noDataMsg")
public String getNoDataMsg() {
return basemodule.getOrDefault("noDataMsg",null)!=null?basemodule.getOrDefault("noDataMsg",null).toString():"";
}
public void setNoDataMsg(String value) {
this._noDataMsg = value;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public String StepApplyText;
@JsonInclude(JsonInclude.Include.NON_NULL)
public String StepBackText;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object rightMenus;
}
@@ -0,0 +1,87 @@
package org.example.Entity.System;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ModuleColor {
private Map row;
//private IPublicUtil util;
private String _cond;
public String Cond;//+get与set
private String _fontColor;
public String FontColor;//+get与set
public Integer FontSize;//+get
private String _backColor;
public String BackColor;//+get与set
public Boolean Bold;//+get
public Boolean IncLine;//+get
public Boolean DeleteLine;
public Boolean UnderLine;
//public Arraylist ToSArray;//Arraylist需处理
//public static String ToStyleStr(){};
/**
* 转换为样式数组
* @return 包含CSS样式的ArrayList
*/
public ArrayList<String> ToSArray() {
ArrayList<String> styles = new ArrayList<>();
// 处理字体颜色
if (FontColor != null && !FontColor.isEmpty()) {
styles.add(String.format("color:'%s'", FontColor));
}
// 处理背景颜色
if (BackColor != null && !BackColor.isEmpty()) {
styles.add(String.format("'background-color':'%s'", BackColor));
}
// 处理加粗
if (Bold != null && Bold) {
styles.add("'font-weight':600");
}
// 处理字体大小
if (FontSize != null && FontSize > 0) {
styles.add(String.format("'font-size':'%dpx'", FontSize));
}
// 处理斜体
if (IncLine != null && IncLine) {
styles.add("'font-style':'italic'");
}
// 处理删除线和下划线(注意:删除线优先级高于下划线)
if (DeleteLine != null && DeleteLine) {
styles.add("'text-decoration':'line-through'");
} else if (UnderLine != null && UnderLine) {
styles.add("'text-decoration':'underline'");
}
return styles;
}
/**
* 将样式数组转换为样式字符串
* @param styles 样式数组
* @return 格式化后的CSS样式字符串,如"{color:'red', 'font-weight':600}"
*/
public static String ToStyleStr(List<String> styles) {
if (styles == null || styles.isEmpty()) {
return null;
}
// 拼接样式项为逗号分隔的字符串
StringBuilder sb = new StringBuilder();
for (int i = 0; i < styles.size(); i++) {
sb.append(styles.get(i));
if (i < styles.size() - 1) {
sb.append(",");
}
}
return String.format("{%s}", sb);
}
}
@@ -0,0 +1,266 @@
package org.example.Entity.System;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Utils.DataTableUtil;
import org.example.Utils.JSON;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Objects;
import static org.example.Utils.DataTableUtil.get;
import static org.example.Utils.NativeExtensionUtils.toBoolean;
public class ModuleEntity {
private static final Logger log = LoggerFactory.getLogger(ModuleEntity.class);
@JsonIgnore
public Map<String, Object> basemodule = new HashMap<>();
public ModuleEntity() {
}
public ModuleEntity(Map<String, Object> basemodule) {
this.basemodule = basemodule;
}
protected Map<String, Object> getBasemodule() {
return basemodule;
}
private String MasterTable; // 私有字段
@JsonProperty("MasterTable")
public String getMasterTable() {
return MasterTable;
}
public void setMasterTable(String value) {
this.MasterTable = value;
}
private String _fromkey;
@JsonIgnore
@JsonProperty("Fromkey")
public String getFromkey() {
Object _fk = basemodule.getOrDefault("fromkey", _fromkey);
if (_fk != null && !(_fk.toString().isEmpty())) {
return (_fromkey = _fk.toString());
}
return null;
}
public void setFromkey(String value) {
this._fromkey = value;
}
private String _menuName;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("MenuName")
public String getMenuName() {
// 先尝试获取 "menuname",如果不存在则获取 "menucaption",最后使用 _menuName 作为默认值
Object value = basemodule.getOrDefault("menuname",
basemodule.getOrDefault("menucaption", _menuName));
if (value != null && !value.toString().isEmpty()) {
return (_menuName = value.toString());
}
return null;
}
public void setMenuName(String value) {
this._menuName = value;
}
private String _toolsName;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ToolsName")
public String getToolsName() {
if (_toolsName == null) {
// 2. 替换为和 C# 一致的取值对象(_row 等效对象,比如 basemodule 是 Map 的话)
Object toolsNameObj = basemodule.getOrDefault("ToolsName", _toolsName); // 替代 C# 的 _row.Get(...)
// 3. 安全转字符串(避免 NPE,对齐 C# 的 as string
_toolsName = toolsNameObj != null ? toolsNameObj.toString() : null;
}
// 4. 对齐 C# 的相等判断逻辑
if (Objects.equals(_toolsName, getMenuName())) {
return null;
}
// 5. 返回最终值
return _toolsName;
}
private String _moduleId;
@JsonProperty("ModuleId")
public String getModuleId() {
Object value = get(basemodule, "MenuCode", _moduleId);
if (value != null && !value.toString().isEmpty()) {
return (_moduleId = value.toString());
}
return null;
}
public void setModuleId(String value) {
this._moduleId = value;
}
private String _menuPrefix;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("MenuPrefix")
public String getMenuPrefix() {
String prefix = (String) get(basemodule, "MenuPrefix", _menuPrefix, null);
if (prefix != null && !prefix.isEmpty()) {
_menuPrefix = prefix.toLowerCase();
}
return _menuPrefix == null ? "" : _menuPrefix;
}
public void setMenuPrefix(String value) {
this._menuPrefix = value;
}
private String _menuId;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("MenuId")
public String getMenuId() {
Object value = basemodule.getOrDefault("MenuId", _menuId);
if (value != null && !value.toString().isEmpty()) {
return (_menuId = value.toString());
}
return null;
}
public void setMenuId(String value) {
this._menuId = value;
}
private String IdField;
@JsonProperty("IdField")
public String getIdField() {
return IdField;
}
public void setIdField(String idField) {
IdField = idField;
}
@JsonIgnore
public String IdValue;
@JsonIgnore
public String IdentityId;
@JsonIgnore
public Map<String, Object> Updrow;
private Map<String, Object> _leftRecord;
@JsonIgnore
@JsonProperty("LeftRecord")
public Map<String, Object> getLeftRecord() {
if (_leftRecord == null && SLeftRecord != null && !SLeftRecord.isEmpty()) {
try {
_leftRecord = (Hashtable) JSON.Decode(SLeftRecord);
} catch (Exception e) {
// 处理 JSON 解析异常
log.error("Exception caught", e);
}
}
return _leftRecord;
}
public void setLeftRecord(Map<String, Object> value) {
this._leftRecord = value;
}
@JsonIgnore
public Map<String, Object> PopPms;
@JsonIgnore
public String SLeftRecord;
@JsonIgnore
public ModuleEntity ParentModule;
@JsonIgnore
public BaseDetailModule DetailModule;
@JsonIgnore
private Boolean IsAdd;
@JsonIgnore
@JsonProperty("IsAdd")
public boolean getIsAdd() {
return IdValue == null || IdValue.trim().isEmpty();
}
private Boolean _noGridLine = null;
@JsonIgnore
public Boolean NoGridLine;
@JsonIgnore
@JsonProperty("NoGridLine")
public Boolean getNoGridLine() {
if (_noGridLine == null) {
_noGridLine = toBoolean(get(basemodule, "noGridLine", null));
}
return _noGridLine != null && _noGridLine ? Boolean.TRUE : null;
}
public void setNoGridLine(Boolean value) {
this._noGridLine = value;
}
private Boolean _hideColumnHeader = null;
@JsonIgnore
public Boolean HideColumnHeader;
@JsonIgnore
@JsonProperty("HideColumnHeader")
public Boolean getHideColumnHeader() {
if (_hideColumnHeader == null) {
_hideColumnHeader = toBoolean(get(basemodule, "hideColumnHeader", null));
}
return _hideColumnHeader != null && _hideColumnHeader ? Boolean.TRUE : null;
}
public void setHideColumnHeader(Boolean value) {
this._hideColumnHeader = value;
}
private Boolean _noRownumber = null;
@JsonIgnore
@JsonProperty("NoRownumber")
public Boolean getNoRownumber() {
if (_noRownumber == null) {
_noRownumber = toBoolean(get(basemodule, "noRownumber", null));
}
return _noRownumber != null && _noRownumber ? true : null;
}
public void setNoRownumber(Boolean value) {
this._noRownumber = value;
}
}
@@ -0,0 +1,179 @@
package org.example.Entity.System;
import java.util.ArrayList;
import java.util.List;
public class SpecNo implements Comparable<SpecNo> {
// 字符集合(与C#保持一致,包含数字、小写字母、大写字母,注意重复的's'和'S'
private static final List<Character> valueArray;
static {
valueArray = new ArrayList<>();
// 添加数字 0-9
for (char c = '0'; c <= '9'; c++) {
valueArray.add(c);
}
// 添加小写字母 a-z(包含重复的's'
for (char c = 'a'; c <= 'z'; c++) {
valueArray.add(c);
}
valueArray.add('s'); // 原C#中重复的's'
// 添加大写字母 A-Z(包含重复的'S'和'Y'
for (char c = 'A'; c <= 'Z'; c++) {
valueArray.add(c);
}
valueArray.add('S'); // 原C#中重复的'S'
valueArray.add('Y'); // 原C#中重复的'Y'
}
private char f;
private char e;
private int findex = -1;
private int eindex = -1;
private static int count = -1;
// 构造方法:接收int值
public SpecNo(int val) {
int count = getCount();
int leftIndex = val / count;
if (leftIndex > count) {
leftIndex = leftIndex / count;
}
int sIndex = val % count;
this.f = valueArray.get(leftIndex);
this.e = valueArray.get(sIndex);
}
// 构造方法:接收字符串
public SpecNo(String val) {
String str = "00" + (val == null ? "" : val);
int start = Math.max(0, str.length() - 2);
String sub = str.substring(start);
char[] ca = sub.toCharArray();
this.f = ca[0];
this.e = ca[1];
}
// 构造方法:接收两个字符
public SpecNo(char f, char e) {
this.f = f;
this.e = e;
}
// 获取字符集合长度(缓存)
private static int getCount() {
if (count < 0) {
count = valueArray.size();
}
return count;
}
// 获取f的索引(懒加载)
public int getFIndex() {
if (findex == -1) {
findex = valueArray.indexOf(f);
}
return findex;
}
// 获取e的索引(懒加载)
public int getEIndex() {
if (eindex == -1) {
eindex = valueArray.indexOf(e);
}
return eindex;
}
// 转换为int值
public int toInt() {
return getFIndex() * getCount() + getEIndex();
}
// 比较方法(实现Comparable接口)
@Override
public int compareTo(SpecNo other) {
if (other == null) {
return 1;
}
if (this.getFIndex() > other.getFIndex()) {
return 1;
} else if (this.getFIndex() < other.getFIndex()) {
return -1;
} else {
return Integer.compare(this.getEIndex(), other.getEIndex());
}
}
// 重写equals方法
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
SpecNo specNo = (SpecNo) obj;
return getFIndex() == specNo.getFIndex() && getEIndex() == specNo.getEIndex();
}
// 重写hashCode方法
@Override
public int hashCode() {
return toString().hashCode();
}
// 重写toString方法
@Override
public String toString() {
return f + String.valueOf(e);
}
// 运算符>的替代方法
public boolean greaterThan(SpecNo other) {
if (this.getFIndex() > other.getFIndex()) {
return true;
} else if (this.getFIndex() == other.getFIndex()) {
return this.getEIndex() > other.getEIndex();
}
return false;
}
// 运算符<的替代方法
public boolean lessThan(SpecNo other) {
if (this.getFIndex() < other.getFIndex()) {
return true;
} else if (this.getFIndex() == other.getFIndex()) {
return this.getEIndex() < other.getEIndex();
}
return false;
}
// 运算符+的替代方法
public SpecNo add(int value) {
int val = this.toInt() + value;
return new SpecNo(val);
}
// 运算符-的替代方法
public SpecNo subtract(int value) {
int val = Math.abs(this.toInt() - value);
return new SpecNo(val);
}
// 自增(++)的替代方法
public SpecNo increment() {
return this.add(1);
}
// 自减(--)的替代方法
public SpecNo decrement() {
return this.subtract(1);
}
// 静态方法:从int转换为SpecNo(替代隐式转换)
public static SpecNo valueOf(int value) {
return new SpecNo(value);
}
// 静态方法:从String转换为SpecNo(替代隐式转换)
public static SpecNo valueOf(String value) {
return new SpecNo(value);
}
}
@@ -0,0 +1,615 @@
package org.example.Entity.System;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.servlet.http.HttpServletRequest;
import org.example.Enums.SystemTypeEnums;
import org.example.Utils.DataTableUtil;
import org.example.Utils.PublicUtil;
import java.util.*;
import static org.example.Utils.NativeExtensionUtils.ToInt32;
import static org.example.Utils.NativeExtensionUtils.toBoolean;
public class SystemMenu {
private Map<String, Object> _row;
private List<Map<String, Object>> _soure;
private LoginUserInfo user;
private String _text;
private String _moduleId;
public Integer _serverId; // C#中为public int?Java用Integer表示可空
private String _moduleId1;
private String _menuStruct;
private boolean _converted = false;
private String _library;
private String href;
private String idValue;
private Object pagePms;
private String _defaultImage;
private String _hoverImage;
private String _hoverMenuTip;
private String _billFlag;
private int _orderId = -1;
private List<SystemMenu> _children;
// =========================== 构造方法(与C#逻辑对齐)===========================
// 私有无参构造(禁止外部直接实例化)
private SystemMenu() {
}
// 双参数构造
public SystemMenu(Map<String, Object> row, LoginUserInfo user) {
super();
this._row = row;
this.user = user;
}
// 三参数构造
public SystemMenu(Map<String, Object> row, List<Map<String, Object>> soure, LoginUserInfo user) {
super();
this._row = row;
this._soure = soure;
this.user = user;
}
// =========================== 属性:ctx(替代C# HttpContext.Current===========================
// 注:Java Web中需通过请求上下文获取,此处模拟C#逻辑(若用Spring可替换为RequestContextHolder
private HttpServletRequest getCtx() {
// 实际项目需根据框架调整(如SpringRequestContextHolder.getRequestAttributes().getRequest()
return null;
}
// =========================== 核心属性(按C#逻辑实现)===========================
/**
* MenuId:从Map<String,Object>取"id"/"menuid"字段,默认0
*/
@JsonProperty("MenuId")
public Integer getMenuId() {
Object value = DataTableUtil.getRowVal(_row, new String[]{"id", "MenuId"}, 0);
return ToInt32(value); // 替代C# ToInt32(),需自定义工具方法
}
/**
* GroupCaption:从Map<String,Object>取"GroupCaption"字段,默认null
*/
@JsonProperty("GroupCaption")
public String getGroupCaption() {
Object value = DataTableUtil.getRowVal(_row, "GroupCaption", null);
return value == null ? null : value.toString();
}
/**
* textJSON序列化忽略null,优先取_userText,否则从Map<String,Object>取"MenuCaption"
*/
@JsonInclude(JsonInclude.Include.NON_NULL) // 替代Newtonsoft NullValueHandling.Ignore
@JsonProperty("text")
public String getText() {
if (_text == null) {
Object value = DataTableUtil.getRowVal(_row, "MenuCaption", null);
_text = value == null ? null : value.toString();
}
return _text;
}
public void setText(String text) {
this._text = text;
}
/**
* ModuleId:复杂逻辑(解析URL参数、提取moduleId等)
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ModuleId")
public String getModuleId() {
// 优先使用已设置的值,否则从Map<String,Object>取"MenuCode"
if (_moduleId == null) {
Object value = DataTableUtil.getRowVal(_row, "MenuCode", null);
_moduleId = value == null ? null : value.toString();
}
// 解析包含"app.html"的URL参数(过滤username/password,提取xtype/moduleId等)
if (_moduleId != null && _moduleId.contains("app.html")) {
try {
Map<String, String> queryPms = new HashMap<>();
String[] urlParts = _moduleId.split("\\?"); // Java中?需转义
if (urlParts.length > 1) {
String queryStr = urlParts[1];
String[] kvPairs = queryStr.split("&");
for (String kvStr : kvPairs) {
String[] kvs = kvStr.split("=");
// 过滤username/password,且确保键值对完整
if (kvs.length == 2
&& !"username".equals(kvs[0].toLowerCase())
&& !"password".equals(kvs[0].toLowerCase())) {
queryPms.put(kvs[0].toLowerCase(), kvs[1]);
}
}
}
// 提取xtype/moduleId/idValue等参数
if (queryPms.containsKey("xtype")) {
String moduleId = queryPms.getOrDefault("moduleid",
queryPms.getOrDefault("dllcoid", ""));
if (!moduleId.isEmpty()) {
this._moduleId = moduleId; // 更新ModuleId
this._library = queryPms.get("xtype");
this.idValue = queryPms.getOrDefault("idvalue",
queryPms.getOrDefault("id", ""));
}
this.pagePms = queryPms;
}
} catch (Exception e) {
// 原C#空catch,Java保留相同逻辑(实际项目建议日志打印)
}
}
return _moduleId;
}
public void setModuleId(String moduleId) {
this._moduleId = moduleId;
}
/**
* serverId:可空int,优先取已设置值,否则从Map<String,Object>取"serverid"(默认0
*/
@JsonProperty("serverId")
public Integer getServerId() {
if (_serverId == null) {
Object value = _row.getOrDefault("serverid", "0"); // 假设Map<String,Object>有get(key, defaultValue)方法
_serverId = ToInt32(value);
}
return _serverId > 0 ? _serverId : null;
}
public void setServerId(Integer serverId) {
this._serverId = serverId;
}
/**
* ModuleId1:从Map<String,Object>取"MenuCode1",默认null
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ModuleId1")
public String getModuleId1() {
if (_moduleId1 == null) {
Object value = DataTableUtil.getRowVal(_row, "MenuCode1", null);
_moduleId1 = value == null ? null : value.toString();
}
return _moduleId1;
}
public void setModuleId1(String moduleId1) {
this._moduleId1 = moduleId1;
}
/**
* MenuStruct:从Map<String,Object>取"MenuStruct",默认null
*/
@JsonProperty("MenuStruct")
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getMenuStruct() {
if (_menuStruct == null) {
Object value = DataTableUtil.getRowVal(_row, "MenuStruct", null);
_menuStruct = value == null ? null : value.toString();
}
return _menuStruct;
}
public void setMenuStruct(String menuStruct) {
this._menuStruct = menuStruct;
}
/**
* ParentId:从Map<String,Object>取"ParentId"(默认0),转字符串返回
*/
@JsonProperty("ParentId")
public String getParentId() {
return Objects.toString(DataTableUtil.getRowVal(_row, "ParentId", 0), "");
}
/**
* Level:从Map<String,Object>取"level"(默认0),JSON序列化忽略
*/
@JsonIgnore // 替代Newtonsoft.Json.JsonIgnore
public int getLevel() {
Object value = DataTableUtil.getRowVal(_row, "level", 0);
return ToInt32(value);
}
/**
* ModuleName:关联_library,含ConvertToModuleName逻辑,JSON序列化忽略null
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("ModuleName")
public String getModuleName() {
// 优先取已设置值,否则从Map<String,Object>取"Library"
if (_library == null) {
Object value = DataTableUtil.getRowVal(_row, "Library", null);
_library = value == null ? null : value.toString();
}
// 仅转换一次(_converted标记)
if (!_converted) {
boolean[] isUrl = new boolean[1]; // Java无out参数,用数组接收
_library = convertToModuleName(_library, 1, isUrl);
_converted = true;
// 若为URL,同步设置href
if (isUrl[0]) {
this.href = _library;
}
}
return _library;
}
public void setModuleName(String moduleName) {
this._library = moduleName;
}
// =========================== 其他简单属性(直接映射)===========================
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("href")
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("idValue")
public String getIdValue() {
return idValue;
}
public void setIdValue(String idValue) {
this.idValue = idValue;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("pagePms")
public Object getPagePms() {
return pagePms;
}
public void setPagePms(Object pagePms) {
this.pagePms = pagePms;
}
/**
* ReadAble:用户查看权限判断(优先级:用户ID→角色ID→操作权限)
*/
@JsonProperty("ReadAble")
public boolean isReadAble() {
boolean has = true;
String readUserIds = getReadUserIds();
// 1. 优先判断"查看用户IDs"
if (readUserIds != null && !readUserIds.isEmpty()) {
has = ("," + readUserIds + ",").contains("," + user.UserId + ",");
}
// 2. 无用户权限时,判断"查看角色IDs"
if ((!has || (readUserIds == null || readUserIds.isEmpty()))
&& getRoleReadIds() != null && !getRoleReadIds().isEmpty()) {
has = isRoleReadAble();
}
// 3. 前两者无权限时,判断操作权限
if (!has && ((getOperuserIds() != null && !getOperuserIds().isEmpty())
|| (getRoleOperIds() != null && !getRoleOperIds().isEmpty()))) {
return isOperAble();
}
return has;
}
/**
* OperAble:用户操作权限判断(优先级:用户ID→角色ID)
*/
@JsonProperty("OperAble")
public boolean isOperAble() {
boolean has = true;
String operUserIds = getOperuserIds();
// 1. 优先判断"操作用户IDs"
if (operUserIds != null && !operUserIds.isEmpty()) {
has = ("," + operUserIds + ",").contains("," + user.UserId + ",");
}
// 2. 无用户权限时,判断"操作角色IDs"
if ((!has || (operUserIds == null || operUserIds.isEmpty()))
&& getRoleOperIds() != null && !getRoleOperIds().isEmpty()) {
return isRoleOperAble();
}
return has;
}
/**
* ReadUserIds:私有属性,从Map<String,Object>取"ReadPurview"
*/
@JsonProperty("ReadUserIds")
private String getReadUserIds() {
Object value = DataTableUtil.getRowVal(_row, "ReadPurview", null);
return value == null ? null : value.toString();
}
/**
* OperuserIds:私有属性,从Map<String,Object>取"OperPurview"
*/
@JsonProperty("OperuserIds")
private String getOperuserIds() {
Object value = DataTableUtil.getRowVal(_row, "OperPurview", null);
return value == null ? null : value.toString();
}
/**
* RoleReadAble:角色查看权限判断
*/
@JsonProperty("RoleReadAble")
public boolean isRoleReadAble() {
boolean has = true;
String roleReadIds = getRoleReadIds();
if (roleReadIds != null && !roleReadIds.isEmpty()) {
has = false;
String[] userRoles = user.getRoleIds(); // 假设LoginUserInfo的roleIds是String数组
if (userRoles != null && userRoles.length > 0) {
for (String role : roleReadIds.split(",")) {
for (String userRole : userRoles) {
if (role.equals(userRole)) {
has = true;
break;
}
}
if (has) break;
}
}
}
// 无角色查看权限时,判断角色操作权限
if (!has && getRoleOperIds() != null && !getRoleOperIds().isEmpty()) {
return isRoleOperAble();
}
return has;
}
/**
* RoleOperAble:角色操作权限判断
*/
@JsonProperty("RoleOperAble")
public boolean isRoleOperAble() {
boolean has = true;
String roleOperIds = getRoleOperIds();
if (roleOperIds != null && !roleOperIds.isEmpty()) {
has = false;
String[] userRoles = user.getRoleIds();
if (userRoles != null && userRoles.length > 0) {
for (String role : roleOperIds.split(",")) {
for (String userRole : userRoles) {
if (role.equals(userRole)) {
has = true;
break;
}
}
if (has) break;
}
}
}
return has;
}
/**
* RoleReadIds:私有属性,从Map<String,Object>取"RoleReadPurview"
*/
@JsonProperty("RoleReadIds")
private String getRoleReadIds() {
Object value = DataTableUtil.getRowVal(_row, "RoleReadPurview", null);
return value == null ? null : value.toString();
}
/**
* RoleOperIds:私有属性,从Map<String,Object>取"RoleOperPurview"
*/
@JsonProperty("RoleOperIds")
private String getRoleOperIds() {
Object value = DataTableUtil.getRowVal(_row, "RoleOperPurview", null);
return value == null ? null : value.toString();
}
/**
* AppUseAble:从Map<String,Object>取"AppUseFlag",取反返回(JSON忽略)
*/
@JsonIgnore
public boolean isAppUseAble() {
Object value = DataTableUtil.getRowVal(_row, "AppUseFlag", null);
return !toBoolean(value); // 替代C# ToBoolean()
}
/**
* ShowCount:从Map<String,Object>取"needcount",转布尔值
*/
@JsonProperty("ShowCount")
public boolean isShowCount() {
Object value = DataTableUtil.getRowVal(_row, "needcount", null);
return toBoolean(value);
}
/**
* DefaultImage:从Map<String,Object>取"DefaultImage",默认null
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("DefaultImage")
public String getDefaultImage() {
if (_defaultImage == null) {
Object value = DataTableUtil.getRowVal(_row, "DefaultImage", null);
_defaultImage = value == null ? null : value.toString();
}
return _defaultImage;
}
public void setDefaultImage(String defaultImage) {
this._defaultImage = defaultImage;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("HoverImage")
public String getHoverImage() {
if (_hoverImage == null) {
Object value = DataTableUtil.getRowVal(_row, "HoverImage", null);
_hoverImage = value != null ? value.toString() : null; // 一行完成判空+赋值
}
return _hoverImage;
}
public void setHoverImage(String hoverImage) {
this._hoverImage = hoverImage;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("HoverMenuTip")
public String getHoverMenuTip() {
if (_hoverMenuTip == null) {
Object value = DataTableUtil.getRowVal(_row, "HoverMenuTip", null);
_hoverMenuTip = value != null ? value.toString() : null; // 一行完成判空+赋值
}
return _hoverMenuTip;
}
public void setHoverMenuTip(String hoverMenuTip) {
this._hoverMenuTip = hoverMenuTip;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("BillFlag")
public String getBillFlag() {
if (_billFlag == null) {
Object value = DataTableUtil.getRowVal(_row, "BillFlag", null);
_billFlag = value != null ? value.toString() : null; // 一行完成判空+赋值
}
return _billFlag;
}
public void setBillFlag(String billFlag) {
this._billFlag = billFlag;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("OrderId")
public Integer getOrderId() {
if (_orderId==-1){
Object value = DataTableUtil.getRowVal(_row, "OrderID", null);
_orderId=value != null ? ToInt32(value) : _orderId; ;
}
return _orderId;
}
public void setOrderId(Integer orderId) {
this._orderId = orderId;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty("Children")
public List<SystemMenu> getChildren() {
// 1. 对应 C#: if (_soure != null)
if (_soure != null && !_soure.isEmpty()) {
// 2. 对应 C#: _children ?? (_children = ...) → 懒加载+缓存
if (_children == null) {
_children = new ArrayList<>();
// 3. 遍历 _source(对应 C#: from row in _soure.AsEnumerable()
for (Map<String, Object> row : _soure) {
// 4. 筛选条件:(row["ParentId"] + "") == MenuId + ""(对齐 C# 的 where 条件)
String parentId = DataTableUtil.getStringValue(row, "ParentId"); // 行的ParentId转字符串
String currentMenuId = this.getMenuId() != null ? this.getMenuId().toString() : ""; // 当前菜单ID转字符串
// 匹配条件:子菜单的ParentId = 当前菜单的MenuId
if (Objects.equals(parentId, currentMenuId)) {
// 5. 对应 C#: select new SystemMenu(row, _soure, user)
SystemMenu childMenu = new SystemMenu(row, _soure, this.user);
_children.add(childMenu);
}
}
}
}
// 6. 对应 C#: _soure 为null时返回 _children
return _children;
}
public void setChildren(List<SystemMenu> children) {
this._children = children;
}
public static String convertToModuleName(String dllName, Integer dllType, boolean[] isUrl) {
// 初始化输出参数
isUrl[0] = false;
// 处理空值并转换为小写
String name = "";
String lwDllName = (dllName == null ? "" : dllName).trim()
.replace("\r\n", "")
.toLowerCase();
// 空值检查
if (dllName == null || dllName.trim().isEmpty()) {
return "";
}
// 判断是否为 URL
if (dllName.startsWith("http") || dllName.startsWith("www")
|| dllName.startsWith("ftp") || dllName.startsWith("/")
|| dllName.indexOf(".html?") > -1) {
isUrl[0] = true;
Map<String, Object> pms = new HashMap<>();
return PublicUtil.ReqSqlPms(null, null, dllName, SystemTypeEnums.PmType.sql, null);
}
// 检查是否为 .dll 或 .lsp 文件
if (!lwDllName.endsWith(".dll") && !lwDllName.endsWith(".lsp")) {
return dllName;
}
// 处理特定 DLL 名称
if (lwDllName.equals("miniblink.dll")) {
return "plugins.PubBrower.Index";
}
if (lwDllName.equals("lskj.billinfo.dll")) {
return "plugins.pubbillinfo.Index";
}
// 通用处理逻辑
name = lwDllName.replace("_", ".");
String[] dlls = name.split("\\."); // 注意:Java 中.需要转义
if (dlls.length == 3 && name.startsWith("lskj")) {
name = name.replace(".dll", ".index");
}
name = name.replace("lskj.", "plugins.").replace(".dll", "");
// 处理特殊名称
if (name.contains("pubadd")) {
name = "plugins.PubModule.PubAdd";
} else if (name.equals("pubspec")) {
name = "plugins.pubspec.index";
} else if (name.equals("leftgridiframe")) {
name = "plugins.leftgridiframe.index";
} else if (name.contains("pubprint.lsp")) {
name = "plugins.pubprint.index";
} else if (name.endsWith(".lsp")) {
name = name.replace("\\", ".").replace(".lsp", "");
}
return name;
}
}
@@ -0,0 +1,76 @@
package org.example.Entity.System;
import org.example.Utils.DataTableUtil;
import java.util.Map;
import java.util.Objects;
/**
* 说明:
* 创建时间:2018-12-29 11:12:05
* 编辑人:
* 编辑时间:
* 备注:
*/
public class UpdStrModule {
protected Map<String, Object> row;
public static final String GuidKeyName = "fk";
public static final String TableNameName = "bn";
public static final String IdFieldName = "k";
public static final String IdValueName = "v";
public static final String IdentityIdName = "Id";
private String idValue;
private String identityId;
public UpdStrModule(Map<String, Object> row) {
this.row = row;
}
public String getGuidKey() {
return DataTableUtil.get(row, GuidKeyName, "") + "";
}
public String getTableName() {
return DataTableUtil.get(row, TableNameName, "") + "";
}
public String getIdField() {
return DataTableUtil.get(row, IdFieldName, "") + "";
}
public String getIdValue() {
if (idValue == null) {
idValue = Objects.toString(DataTableUtil.get(row, IdValueName, ""), "");
}
return idValue;
}
public void setIdValue(String idValue) {
this.idValue = idValue;
}
public String getIdentityId() {
if (identityId == null) {
identityId = DataTableUtil.get(row, IdentityIdName, "") + "";
}
return identityId;
}
public void setIdentityId(String identityId) {
this.identityId = identityId;
}
public boolean Valide() {
return !isBlank(getGuidKey()) &&
!isBlank(getTableName()) &&
!isBlank(getIdField()) &&
!(isBlank(getIdValue()) && isBlank(getIdentityId()));
}
// 工具方法:判断字符串是否为空白(null或空字符串)
private boolean isBlank(String str) {
return str == null || str.trim().isEmpty();
}
}
@@ -0,0 +1,88 @@
package org.example.Enums;
public class CusGridColumnPrefix {
/**
* 基础档案、报表左侧表格
*/
public static final String BaseLeftGridView = "BaseLeftGridView_";
/**
* 基础档案、报表主表格
*/
public static final String BaseMainGridView = "BaseMainGridView_";
/**
* 基础档案、报表右侧表格
*/
public static final String BaseRightGridView = "BaseRightGridView_";
/**
* 基础档案、报表底部表格
*/
public static final String BaseDetailGridView = "BaseDetailGridView_";
/**
* 基础审核主表格
*/
public static final String BaseAuditMainGridView = "BaseAuditMainGridView_";
/**
* 单据来源表格
*/
public static final String BillSourceGridView = "BillLeftGridView_";
/**
* 单据明细表格
*/
public static final String BillDetailGridView = "BillDetailGridView_";
/**
* 单据来源明细表格
*/
public static final String BillSourceDetailGridView = "BillSourceDetailGridView_";
/**
* 单据来源明细附加信息表格
*/
public static final String BillSourceDetailAttachGridView = "BillSourceDetailAttachGridView_";
/**
* 单据审核主表格
*/
public static final String AuditMainGridView = "AuditMainGridView_";
/**
* 单据审核弹出框明细表格
*/
public static final String AuditPopupDetailGridView = "AuditPopupDetailGridView_";
/**
* 单据审核弹出选项卡数据的表格
*/
public static final String AuditPopupBasicInfoGridView = "AuditPopupBasicInfoGridView_";
/**
* 单据审核弹出框附加信息表格
*/
public static final String AuditPopupAttachGridView = "AuditPopupAttachGridView_";
/**
* 单据已完成单据主表格
*/
public static final String AuditOverMainGridView = "AuditOverMainGridView_";
/**
* 单据已完成单据明细表格
*/
public static final String AuditOverDetailGridView = "AuditOverDetailGridView_";
/**
* 附件表格
*/
public static final String AttachGridView = "AttachGridView_";
/**
* 单据详情表格
*/
public static final String BillInfoGridView = "BillInfoGridView_";
}
@@ -0,0 +1,17 @@
package org.example.Enums;
import org.springframework.jdbc.core.SqlInOutParameter;
import org.springframework.jdbc.core.SqlParameter;
// 4. 输入输出参数子类(继承 SqlInOutParameter
public class CustomInOutParameter extends CustomSqlParameter {
public CustomInOutParameter(String name, int sqlType, String mode) {
super(name, sqlType, mode, ParameterDirection.INPUT_OUTPUT);
}
@Override
public SqlParameter toSpringSqlParameter() {
// 返回 Spring 原生的 SqlInOutParameter(明确 INPUT_OUTPUT
return new SqlInOutParameter(name, sqlType);
}
}
@@ -0,0 +1,17 @@
package org.example.Enums;
import org.springframework.jdbc.core.SqlParameter;
// 2. 输入参数子类(继承 SqlParameter
public class CustomInParameter extends CustomSqlParameter {
public CustomInParameter(String name, int sqlType, String mode) {
super(name, sqlType, mode, ParameterDirection.INPUT);
}
// 关键:重写方法,返回 Spring 原生的 SqlParameter(输入类型)
@Override
public SqlParameter toSpringSqlParameter() {
// 直接创建并返回原生 SqlParameter,确保方向为 INPUT
return new SqlParameter(this.name, this.sqlType);
}
}
@@ -0,0 +1,16 @@
package org.example.Enums;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
// 3. 输出参数子类(继承 SqlOutParameter
public class CustomOutParameter extends CustomSqlParameter {
public CustomOutParameter(String name, int sqlType, String mode) {
super(name, sqlType, mode, ParameterDirection.OUTPUT);
}
@Override
public SqlParameter toSpringSqlParameter() {
return new SqlOutParameter(this.name, this.sqlType);
}
}
@@ -0,0 +1,77 @@
package org.example.Enums;
import org.example.Enums.ParameterDirection;
import org.springframework.jdbc.core.SqlInOutParameter;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
// 1. 抽象基类:定义公共属性和方法
public abstract class CustomSqlParameter {
protected String name;
protected int sqlType;
protected String mode;
protected ParameterDirection direction;
protected Object value;
public CustomSqlParameter(String name, int sqlType, String mode, ParameterDirection direction) {
this.name = name;
this.sqlType = sqlType;
this.mode = mode;
this.direction = direction;
}
public CustomSqlParameter(String name, int sqlType, String mode, ParameterDirection direction, Object value) {
this.name = name;
this.sqlType = sqlType;
this.mode = mode;
this.direction = direction;
this.value = value;
}
// 抽象方法:返回对应的 Spring 原生参数对象(关键)
public abstract SqlParameter toSpringSqlParameter();
// Getter 方法
public String getName() {
return name;
}
public Object getValue() {
return value;
}
public void setName(String name) {
this.name = name;
}
public void setSqlType(int sqlType) {
this.sqlType = sqlType;
}
public void setMode(String mode) {
this.mode = mode;
}
public void setDirection(ParameterDirection direction) {
this.direction = direction;
}
public void setValue(Object value) {
this.value = value;
}
public int getSqlType() {
return sqlType;
}
public String getMode() {
return mode;
}
public ParameterDirection getDirection() {
return direction;
}
}
@@ -0,0 +1,17 @@
package org.example.Enums;
public enum LoginCode {
Redirect(0),
ResetPwd(-1),
WxRedirect(-2);
private final int value;
LoginCode(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
@@ -0,0 +1,16 @@
package org.example.Enums;
/**
* 使用JdbcTemplate直接执行查询并返回多结果集
* <p>
* // * @param querySql 包含多个结果集的SQL语句
*
* @return 多结果集列表,每个元素为一个结果集(List<Map<String, Object>>
*/
public enum ParameterDirection {
INPUT, // 输入参数
OUTPUT, // 输出参数
INPUT_OUTPUT,// 输入输出参数
RETURN_VALUE // 返回值参数
}
@@ -0,0 +1,394 @@
package org.example.Enums;
/**
* 系统枚举集合
* 包含控件类型、消息表类型、模块类型等多种枚举
* 创 建 者:zyw
* 创建日期:2016-06-28 15:50:32
*/
public class SystemEnums {
/**
* 控件类型
*/
public enum ControlType {
LabText(0, "文本框"),
LabComboxValue(1, "下拉框 获取Value值"),
LabComboxText(2, "下拉框 获取Text值"),
LabTreeType(3, ""),
LabDate(4, "日期(年-月-日)"),
LabDateTime(44, "日期和时间(年-月-日 时-分-秒)"),
LabDateTimeShort(444, "日期短时间(年-月-日 时-分)"),
LabTime(4444, "时间(时-分-秒)"),
LabShortTime(44444, "短时间(时-分)"),
LabYearTime(444444, "时间(年-月)"),
LabAutoCompleteValue(5, "自动搜索 获取Value值"),
LabAutoCompleteText(6, "自动搜索 获取Text值"),
LabTextInt(7, "数字控件"),
LabPassword(8, "密码框"),
LabRemark(9, "备注"),
LabWWW(10, "网址"),
LabQQ(11, "QQ"),
LabPhone(12, "电话拨号(手机端拨号)"),
LabVPhone(200, "如果是web端,那么就带发短信验证码功能"),
LabMultiSelectValue(13, "多选,获取Value"),
LabMultiSelectText(14, "多选,获取Text"),
LabAutoCompleteValueParam(15, "自动搜索 获取Value值,需要带参数"),
LabAutoCompleteTextParam(16, "自动搜索 获取Text值,需要带参数"),
LabCheckBox(17, "复选框"),
LabComboxCheckListValue(18, ""),
LabComboxCheckListText(19, ""),
LabMemoEdit(20, "Memo控件"),
LabCheckComboxValue(21, ""),
LabCheckComboxText(22, ""),
LabComboxInputParam(23, "Combox获取Text值,需要带参数 宜宾项目为36"),
LabCheckDateEx(24, ""),
LabCheckAutoSeacherValue(25, ""),
LabCheckAutoSeacherText(26, ""),
LabCalcText(27, "计算器"),
LabMultiSelectValueParam(33, "多选 获取Value值,需要带参数"),
LabMultiSelectTextParam(34, "多选 获取Text值,需要带参数"),
LabComboxValueParam(35, "Combox获取Value值,需要带参数"),
LabComboxTextParam(36, "下拉列表框(带参数) 保存Value值,显示Text值"),
LabRichEdit(37, "富文本编辑框"),
LabSmartQueryReturnID(38, "智能搜索返回ID"),
LabSmartQueryReturnName(39, "智能搜索返回Name"),
LabSmartQueryReturnIDWithParam(40, "智能搜索返回ID 带参数"),
LabSmartQueryReturnNameWithParam(41, "智能搜索返回Name 带参数"),
LabProgress(96, "进度条"),
LabMap(97, "地图(手机端)"),
LabOSacn(98, "扫码(手机端) 条码"),
LabPic(99, "图片"),
LabPicEx(100, "图片,存地址"),
LabTSacn(101, "扫码(手机端) 二维码"),
LabWinBtnsValue(102, ""),
LabWinBtnsText(103, ""),
LabWinMultiBtnsValue(104, ""),
LabWinMultiBtnsText(105, ""),
LabRadioGroupValue(106, "单选框组"),
LabRadioGroupText(107, "单选框组"),
LabWinGridValue(109, ""),
LabWinGridText(110, ""),
LabWinMultiGridValue(111, ""),
LabWinMultiGridText(112, ""),
LabModuleSelectValues(42, "弹出模块选行数据,根据行数据自动填充表单字段"),
LabModuleMultiSelectValues(43, "弹出模块多选行数据,根据行数据自动填充表单字段"),
LabComboxModuleValueParam(116, "弹窗模块选择value"),
LabComboxModuleTextParam(117, "弹窗模块选择text"),
LabComTreeboxValue(118, "下拉树返回value"),
LabComTreeboxText(119, "下拉树返回text"),
LabComTreeboxValueParam(120, "下拉树返回value带参数"),
LabComTreeboxTextParam(121, "下拉树返回text带参数"),
LabComTreeboxLeafValue(122, "下拉树返回value带参数"),
LabComTreeboxLeafText(123, "下拉树返回text带参数"),
LabComTreeboxLeafValueParam(124, "下拉树返回value带参数"),
LabComTreeboxLeafTextParam(125, "下拉树返回text带参数"),
LabComStarValueParam(126, "下拉树返回value带参数"),
LabComStarTextParam(127, "下拉树返回text带参数"),
LabSignature(128, "签字框"),
LabJointRemark(129, "签字框"),
CheckboxGroupValue(130, "多选框组"),
CheckboxGroupText(131, "多选框组"),
LabMultiComTreeboxLeafValue(132, "下拉树返回value"),
LabMultiComTreeboxLeafText(133, "下拉树返回text"),
LabMultiComTreeboxLeafValueParam(134, "下拉树多选返回末级value带参数"),
LabMultiComTreeboxLeafTextParam(135, "下拉树多选返回末级text带参数"),
LabMultiComTreeboxValue(136, "下拉树多选返回value"),
LabMultiComTreeboxText(137, "下拉树多选返回text"),
LabMultiComTreeboxValueParam(138, "下拉树多选返回value带参数"),
LabMultiComTreeboxTextParam(139, "下拉树多选返回text带参数"),
ApiLabText(140, "调用接口的文本"),
LabLink(164,"超链接"),//超链接
LabModuleLink(165,"超链接"),//超链接
LabEleScale(170,""),
LabCheckDateTimeEx(244, ""),
LabCheckDateTimeShort(2444, ""),
LabCheckTime(24444, ""),
LabCheckShortTime(244444, ""),
LabLabYearTime(2444444, "");
private final int value;
private final String description;
ControlType(int value, String description) {
this.value = value;
this.description = description;
}
public int getValue() {
return value;
}
public String getDescription() {
return description;
}
public static ControlType fromValue(int value) {
for (ControlType type : ControlType.values()) {
if (type.value == value) {
return type;
}
}
throw new IllegalArgumentException("未知的ControlType值: " + value);
}
}
/**
* 消息表类型
*/
public enum MsgTableType {
WX(3),
YunZhiJia(4);
private final int value;
MsgTableType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static MsgTableType fromValue(int value) {
for (MsgTableType type : MsgTableType.values()) {
if (type.value == value) {
return type;
}
}
throw new IllegalArgumentException("未知的MsgTableType值: " + value);
}
}
/**
* 模块类型枚举
*/
public enum ModuleTypeEnum {
Bill,
Module,
Report,
Accraditation,
Other
}
/**
* 模块类型
*/
public enum ModuleType {
BaseModule,
ReportModule,
BillModule
}
/**
* 单据菜单枚举
*/
public enum BillMenuEnum {
BillSource,
BillSourceDetail,
BillDetail
}
/**
* 目标类型
*/
public enum TargetType {
ALL(0),
CS(1),
MOBILE(2),
WEB(3);
private final int value;
TargetType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static TargetType fromValue(int value) {
for (TargetType type : TargetType.values()) {
if (type.value == value) {
return type;
}
}
throw new IllegalArgumentException("未知的TargetType值: " + value);
}
}
/**
* 图表模块类型
*/
public enum ChartType {
Line(1, "折线"),
Bar(2, "柱状图"),
Pie(3, "饼图"),
Map(4, "地图 一般为混搭模式"),
Radar(5, "雷达"),
Candlestick(6, "k线图"),
Boxplot(7, "箱线图"),
Heatmap(8, "热力图"),
Graph(9, "关系图"),
Treemap(10, "矩形树图"),
Parallel(11, "平行坐标"),
Sankey(12, "桑基图"),
Funnel(13, "漏斗"),
Gauge(14, "仪表盘"),
PictorialBar(15, "象形柱图"),
ThemeRiver(16, "主体河流"),
Scatter(17, "散点图");
private final int value;
private final String description;
ChartType(int value, String description) {
this.value = value;
this.description = description;
}
public int getValue() {
return value;
}
public String getDescription() {
return description;
}
public static ChartType fromValue(int value) {
for (ChartType type : ChartType.values()) {
if (type.value == value) {
return type;
}
}
throw new IllegalArgumentException("未知的ChartType值: " + value);
}
}
/**
* 单据状态
*/
public enum BillState {
Canceled(-1, "作废"),
Draft(0, "草稿"),
Applied(1, "提交未审核"),
Aduit(2, "审核中"),
Backed(3, "已退回"),
Over(4, "已完成");
private final int value;
private final String description;
BillState(int value, String description) {
this.value = value;
this.description = description;
}
public int getValue() {
return value;
}
public String getDescription() {
return description;
}
public static BillState fromValue(int value) {
for (BillState state : BillState.values()) {
if (state.value == value) {
return state;
}
}
throw new IllegalArgumentException("未知的BillState值: " + value);
}
}
/**
* 程序事件类型
*/
public enum OperateEvent {
BeforeModuleDataLoad(1),
BeforeModuleDataChange(3),
AfterModuleDataChange(4),
BeforeModuleStateChange(5),
AfterModuleStateChange(6),
BeforeModuleAuditStateChange(7),
AfterModuleAuditStateChange(8),
BeforeModuleContextMenu(9),
AfterModuleContextMenu(10),
BeforeModuleDataDelete(11),
AfterModuleDataDelete(12),
BeforeUploadFile(13),
AfterUploadFile(14),
Loop(99),
Timer(100);
private final int value;
OperateEvent(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static OperateEvent fromValue(int value) {
for (OperateEvent event : OperateEvent.values()) {
if (event.value == value) {
return event;
}
}
throw new IllegalArgumentException("未知的OperateEvent值: " + value);
}
}
/**
* 操作类型
*/
public enum ActionType {
None(-1, "未设置"),
Load(0, "加载数据"),
Add(1, "添加"),
Update(2, "修改"),
Delete(3, "删除"),
Obsolete(4, "作废"),
EscObsolete(5, "取消作废"),
Submit(21, "提交"),
EscSubmit(22, "取消提交"),
Audit(31, "审核"),
AuditBack(32, "反退"),
AuditClose(33, "关闭审核"),
AuditPress(34, "审核催办"),
AuditPause(35, "审核暂停待办"),
AuditForward(36, "审核转发"),
AuditHand(37, "审核转交");
private final int value;
private final String description;
ActionType(int value, String description) {
this.value = value;
this.description = description;
}
public int getValue() {
return value;
}
public String getDescription() {
return description;
}
public static ActionType fromValue(int value) {
for (ActionType type : ActionType.values()) {
if (type.value == value) {
return type;
}
}
throw new IllegalArgumentException("未知的ActionType值: " + value);
}
}
}
@@ -0,0 +1,77 @@
package org.example.Enums;
/**
* 程序类型(对应C#的FieldType枚举)
*/
public class SystemTypeEnums {
public enum FieldType {
Unknown,
Boolean,
SByte,
Byte,
Int16,
UInt16,
Int32,
UInt32,
Int64,
UInt64,
Decimal,
Float,
Double,
SmallMoney,
Money,
SmallDateTime,
DateTime,
AnsiChar,
AnsiVarChar,
AnsiText,
AnsiVarCharMax,
Char,
VarChar,
Text,
VarCharMax,
Binary,
VarBinary,
Image,
VarBinaryMax,
Variant,
TimeStamp,
Guid
}
/**
* 登录类型(对应C#的LoginType枚举,保留指定数值)
*/
public enum LoginType {
CS(1),
Web(2),
Android(3),
IOS(4),
AD(5);
private final int value;
// 构造函数指定枚举值
LoginType(int value) {
this.value = value;
}
// 获取枚举值(类似C#的枚举默认值访问)
public int getValue() {
return value;
}
}
/**
* 替换参数类型(对应C#的PmType枚举)
*/
public enum PmType {
store,
sql,
ignorenull, // 忽略不包含的键
program
}
}

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