refactor: 合并 biz_support_unit/biz_execution_unit/biz_service_org 为 biz_org, 删除 2 张孤儿表, 改 biz_person.work_unit → org_id FK

主要改动:
- SQL: biz_support_unit → biz_org, 加 org_type, 加 business_nature; 删 biz_execution_unit, biz_service_org
- SQL: biz_project.support_unit_id/name + service_org_id/name → org_id/name/type
- SQL: biz_meeting.support_unit_name → org_name
- SQL: biz_person.work_unit → org_id (FK)
- 后端: 新 BizOrg entity/mapper/service/controller
- 后端: BizProject/BizMeeting 字段重命名
- 后端: 删 12 个 BizSupportUnit/BizExecutionUnit/BizServiceOrg Java 文件
- 后端: BizPersonImportVO.workUnit → orgName (导入时查 biz_org 取 org_id)
- 后端: BizAuthController.registerExecutor 完整实现 (原 registerSupplier stub)
- 前端: 新 admin/Orgs.vue + manager/Orgs.vue (原 SupportUnits)
- 前端: RegisterExecutor.vue (原 RegisterSupplier, 单页 2 步)
- 前端: sponsor/executor/manager 多个文件 workUnit → orgId/orgName 重命名
- 前端: 统一 supplier → executor, 业务命名 sponsor(赞助方) / executor(执行方=供应商)
- 前端: 全工程 execution → executor (company type / role / person unit_type)
This commit is contained in:
郭庆泰
2026-08-15 12:41:10 +08:00
commit cf5790229a
694 changed files with 102090 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
custom: http://doc.ruoyi.vip/ruoyi-vue/other/donate.html
+47
View File
@@ -0,0 +1,47 @@
######################################################################
# Build Tools
.gradle
/build/
!gradle/wrapper/gradle-wrapper.jar
target/
!.mvn/wrapper/maven-wrapper.jar
######################################################################
# IDE
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### JRebel ###
rebel.xml
### NetBeans ###
nbproject/private/
build/*
nbbuild/
dist/
nbdist/
.nb-gradle/
######################################################################
# Others
*.log
*.xml.versionsBackup
*.swp
!*/build/*.java
!*/build/*.html
!*/build/*.xml
+20
View File
@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2018 RuoYi
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+115
View File
@@ -0,0 +1,115 @@
<p align="center">
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
</p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.9.2</h1>
<h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
<p align="center">
<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.9.2-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p>
## 平台简介
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
* 前端采用Vue、Element UI。
* 后端采用Spring Boot、Spring Security、Redis & Jwt。
* 权限认证使用Jwt,支持多终端认证系统。
* 支持加载动态权限菜单,多方式轻松权限控制。
* 高效率开发,使用代码生成器可以一键生成前后端代码。
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)&nbsp;&nbsp;
# 版本分支
RuoYi-Vue 后端项目提供 Spring Boot 2.x / 3.x / 4.x 多版本分支的并行维护。
| 名称 | 说明 | 地址 |
| :---------------- | :------------------------ | :------------------------------------------------------ |
| master 默认分支 | Spring Boot 4.x (JDK 17+) | https://gitee.com/y_project/RuoYi-Vue |
| springboot3 分支 | Spring Boot 3.x (JDK 17+) | https://gitee.com/y_project/RuoYi-Vue/tree/springboot3 |
| springboot2 分支 | Spring Boot 2.x (JDK 8+) | https://gitee.com/y_project/RuoYi-Vue/tree/springboot2 |
RuoYi-Vue 前端项目提供 Vue 2.x / 3.x / JavaScript TypeScript 版本均可混用搭配
| 项目名称 | **RuoYi-Vue** | **RuoYi-Vue3** | **RuoYi-Vue3-TypeScript** |
| :--- | :--- | :--- | :--- |
| **前端框架** | Vue 2 | Vue 3 | Vue 3 |
| **脚本语言** | JavaScript | JavaScript | TypeScript |
| **构建工具** | Vue CLI | Vite | Vite |
| **UI 组件库** | Element UI | Element Plus | Element Plus |
| **状态管理** | Vuex | Pinia | Pinia |
| **路由管理** | Vue Router 3 | Vue Router 4 | Vue Router 4 |
| **核心特点** | 1. 技术栈经典稳定<br>2. 社区资料丰富<br>3. 当前维护重心已转移 | 1. 现代前端技术栈<br>2. 开发体验与性能更优<br>3. 官方主推的活跃版本 | 1. 类型加持,减少沟通成本<br>2. 开发时有提示,效率更高<br>3. 多人协作企业级开发项目 |
| **仓库地址** | [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue) | [RuoYi-Vue3](https://gitcode.com/yangzongzhuan/RuoYi-Vue3) | [RuoYi-Vue3-TypeScript](https://gitcode.com/yangzongzhuan/RuoYi-Vue3/tree/typescript) |
## 内置功能
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
3. 岗位管理:配置系统用户所属担任职务。
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
7. 参数管理:对系统动态配置常用参数。
8. 通知公告:系统通知公告信息发布维护。
9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
10. 登录日志:系统登录日志记录查询包含登录异常。
11. 在线用户:当前系统中活跃用户状态监控。
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
14. 系统接口:根据业务代码自动生成相关的api接口文档。
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
16. 缓存监控:对系统的缓存信息查询,命令统计等。
17. 在线构建器:拖动表单元素生成相应的HTML代码。
18. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
## 在线体验
- admin/admin123
- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
演示地址:http://vue.ruoyi.vip
文档地址:http://doc.ruoyi.vip
## 演示图
<table>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/cd1f90be5f2684f4560c9519c0f2a232ee8.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-936ec82d1f4872e1bc980927654b6007307.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/b6115bc8c31de52951982e509930b20684a.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
</tr>
</table>
## 若依前后端分离交流群
QQ群: [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/已满-101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [![加入QQ群](https://img.shields.io/badge/已满-101539465-blue.svg)](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [![加入QQ群](https://img.shields.io/badge/已满-264312783-blue.svg)](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [![加入QQ群](https://img.shields.io/badge/已满-167385320-blue.svg)](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [![加入QQ群](https://img.shields.io/badge/已满-104748341-blue.svg)](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [![加入QQ群](https://img.shields.io/badge/已满-160110482-blue.svg)](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [![加入QQ群](https://img.shields.io/badge/已满-170801498-blue.svg)](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [![加入QQ群](https://img.shields.io/badge/已满-108482800-blue.svg)](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [![加入QQ群](https://img.shields.io/badge/已满-101046199-blue.svg)](https://jq.qq.com/?_wv=1027&k=SpyH2875) [![加入QQ群](https://img.shields.io/badge/已满-136919097-blue.svg)](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [![加入QQ群](https://img.shields.io/badge/已满-143961921-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [![加入QQ群](https://img.shields.io/badge/已满-174951577-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=174951577) [![加入QQ群](https://img.shields.io/badge/已满-161281055-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) [![加入QQ群](https://img.shields.io/badge/已满-138988063-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XIzkm_mV2xTsUtFxo63bmicYoDBA6Ifm&authKey=dDW%2F4qsmw3x9govoZY9w%2FoWAoC4wbHqGal%2BbqLzoS6VBarU8EBptIgPKN%2FviyC8j&noverify=0&group_code=138988063) [![加入QQ群](https://img.shields.io/badge/已满-151450850-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DkugnCg68PevlycJSKSwjhFqfIgrWWwR&authKey=pR1Pa5lPIeGF%2FFtIk6d%2FGB5qFi0EdvyErtpQXULzo03zbhopBHLWcuqdpwY241R%2F&noverify=0&group_code=151450850) [![加入QQ群](https://img.shields.io/badge/已满-224622315-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=F58bgRa-Dp-rsQJThiJqIYv8t4-lWfXh&authKey=UmUs4CVG5OPA1whvsa4uSespOvyd8%2FAr9olEGaWAfdLmfKQk%2FVBp2YU3u2xXXt76&noverify=0&group_code=224622315) [![加入QQ群](https://img.shields.io/badge/已满-287842588-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Nxb2EQ5qozWa218Wbs7zgBnjLSNk_tVT&authKey=obBKXj6SBKgrFTJZx0AqQnIYbNOvBB2kmgwWvGhzxR67RoRr84%2Bus5OadzMcdJl5&noverify=0&group_code=287842588) [![加入QQ群](https://img.shields.io/badge/已满-187944233-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=numtK1M_I4eVd2Gvg8qtbuL8JgX42qNh&authKey=giV9XWMaFZTY%2FqPlmWbkB9g3fi0Ev5CwEtT9Tgei0oUlFFCQLDp4ozWRiVIzubIm&noverify=0&group_code=187944233) [![加入QQ群](https://img.shields.io/badge/已满-228578329-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G6r5KGCaa3pqdbUSXNIgYloyb8e0_L0D&authKey=4w8tF1eGW7%2FedWn%2FHAypQksdrML%2BDHolQSx7094Agm7Luakj9EbfPnSTxSi2T1LQ&noverify=0&group_code=228578329) [![加入QQ群](https://img.shields.io/badge/已满-191164766-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GsOo-OLz53J8y_9TPoO6XXSGNRTgbFxA&authKey=R7Uy%2Feq%2BZsoKNqHvRKhiXpypW7DAogoWapOawUGHokJSBIBIre2%2FoiAZeZBSLuBc&noverify=0&group_code=191164766) [![加入QQ群](https://img.shields.io/badge/已满-174569686-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=PmYavuzsOthVqfdAPbo4uAeIbu7Ttjgc&authKey=p52l8%2FXa4PS1JcEmS3VccKSwOPJUZ1ZfQ69MEKzbrooNUljRtlKjvsXf04bxNp3G&noverify=0&group_code=174569686) [![加入QQ群](https://img.shields.io/badge/127358632-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=M9y5NjAl44lAL_Vh2crmEehZU_PMU6KS&authKey=ZSDz8hEREWSaPuxQV3gEwqGIaGjfRNnkB4rJjf0IvXhrSUGSGwQFmBA%2Boe8HFxyl&noverify=0&group_code=127358632) 点击按钮入群。
Binary file not shown.
+243
View File
@@ -0,0 +1,243 @@
<?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>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId>
<version>3.9.2</version>
<name>ruoyi</name>
<url>http://www.ruoyi.vip</url>
<description>若依管理系统</description>
<properties>
<ruoyi.version>3.9.2</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
<spring-boot.version>4.0.6</spring-boot.version>
<mybatis-spring-boot.version>4.0.1</mybatis-spring-boot.version>
<druid.version>1.2.28</druid.version>
<yauaa.version>8.1.1</yauaa.version>
<kaptcha.version>2.3.3</kaptcha.version>
<pagehelper.boot.version>4.1.0</pagehelper.boot.version>
<fastjson.version>2.0.64</fastjson.version>
<oshi.version>7.3.0</oshi.version>
<commons.io.version>2.22.0</commons.io.version>
<poi.version>4.1.2</poi.version>
<velocity.version>2.3</velocity.version>
<jwt.version>0.9.1</jwt.version>
<jaxb-api.version>2.3.1</jaxb-api.version>
<springdoc.version>3.0.3</springdoc.version>
</properties>
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<!-- SpringBoot的依赖配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-4-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 解析客户端操作系统、浏览器等 -->
<dependency>
<groupId>nl.basjes.parse.useragent</groupId>
<artifactId>yauaa</artifactId>
<version>${yauaa.version}</version>
</dependency>
<!-- pagehelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.boot.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>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb-api.version}</version>
</dependency>
<!-- 获取系统信息 -->
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>${oshi.version}</version>
</dependency>
<!-- spring-doc -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc.version}</version>
</dependency>
<!-- io常用工具类 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
</dependency>
<!-- excel工具 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity.version}</version>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- Token生成与解析-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<!-- 验证码 -->
<dependency>
<groupId>pro.fessional</groupId>
<artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version>
</dependency>
<!-- 定时任务-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-quartz</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 代码生成-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-generator</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 核心模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 系统模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 业务模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-business</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
<version>${ruoyi.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>ruoyi-admin</module>
<module>ruoyi-framework</module>
<module>ruoyi-system</module>
<module>ruoyi-business</module>
<module>ruoyi-quartz</module>
<module>ruoyi-generator</module>
<module>ruoyi-common</module>
</modules>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<parameters>true</parameters>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.ruoyi.RuoYiApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>public</id>
<name>aliyun nexus</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
+95
View File
@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.9.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>ruoyi-admin</artifactId>
<description>
web服务入口
</description>
<dependencies>
<!-- spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 表示依赖不会传递 -->
</dependency>
<!-- spring-doc -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
</dependency>
<!-- Mysql驱动包 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- 核心模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
</dependency>
<!-- 定时任务-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-quartz</artifactId>
</dependency>
<!-- 代码生成-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-generator</artifactId>
</dependency>
<!-- 业务模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-business</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<addResources>true</addResources>
<mainClass>com.ruoyi.RuoYiApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${project.artifactId}</warName>
</configuration>
</plugin>
</plugins>
<finalName>${project.artifactId}</finalName>
</build>
</project>
@@ -0,0 +1,30 @@
package com.ruoyi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
/**
* 启动程序
*
* @author ruoyi
*/
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class RuoYiApplication
{
public static void main(String[] args)
{
// System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(RuoYiApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}
@@ -0,0 +1,18 @@
package com.ruoyi;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/**
* web容器中进行部署
*
* @author ruoyi
*/
public class RuoYiServletInitializer extends SpringBootServletInitializer
{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
return application.sources(RuoYiApplication.class);
}
}
@@ -0,0 +1,94 @@
package com.ruoyi.web.controller.common;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import jakarta.annotation.Resource;
import javax.imageio.ImageIO;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.google.code.kaptcha.Producer;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.service.ISysConfigService;
/**
* 验证码操作处理
*
* @author ruoyi
*/
@RestController
public class CaptchaController
{
@Resource(name = "captchaProducer")
private Producer captchaProducer;
@Resource(name = "captchaProducerMath")
private Producer captchaProducerMath;
@Autowired
private RedisCache redisCache;
@Autowired
private ISysConfigService configService;
/**
* 生成验证码
*/
@GetMapping("/captchaImage")
public AjaxResult getCode(HttpServletResponse response) throws IOException
{
AjaxResult ajax = AjaxResult.success();
boolean captchaEnabled = configService.selectCaptchaEnabled();
ajax.put("captchaEnabled", captchaEnabled);
if (!captchaEnabled)
{
return ajax;
}
// 保存验证码信息
String uuid = IdUtils.simpleUUID();
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
String capStr = null, code = null;
BufferedImage image = null;
// 生成验证码
String captchaType = RuoYiConfig.getCaptchaType();
if ("math".equals(captchaType))
{
String capText = captchaProducerMath.createText();
capStr = capText.substring(0, capText.lastIndexOf("@"));
code = capText.substring(capText.lastIndexOf("@") + 1);
image = captchaProducerMath.createImage(capStr);
}
else if ("char".equals(captchaType))
{
capStr = code = captchaProducer.createText();
image = captchaProducer.createImage(capStr);
}
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
// 转换流信息写出
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try
{
ImageIO.write(image, "jpg", os);
}
catch (IOException e)
{
return AjaxResult.error(e.getMessage());
}
ajax.put("uuid", uuid);
ajax.put("img", Base64.encode(os.toByteArray()));
return ajax;
}
}
@@ -0,0 +1,162 @@
package com.ruoyi.web.controller.common;
import java.util.ArrayList;
import java.util.List;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.framework.config.ServerConfig;
/**
* 通用请求处理
*
* @author ruoyi
*/
@RestController
@RequestMapping("/common")
public class CommonController
{
private static final Logger log = LoggerFactory.getLogger(CommonController.class);
@Autowired
private ServerConfig serverConfig;
private static final String FILE_DELIMITER = ",";
/**
* 通用下载请求
*
* @param fileName 文件名称
* @param delete 是否删除
*/
@GetMapping("/download")
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
{
try
{
if (!FileUtils.checkAllowDownload(fileName))
{
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
}
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
String filePath = RuoYiConfig.getDownloadPath() + fileName;
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, realFileName);
FileUtils.writeBytes(filePath, response.getOutputStream());
if (delete)
{
FileUtils.deleteFile(filePath);
}
}
catch (Exception e)
{
log.error("下载文件失败", e);
}
}
/**
* 通用上传请求(单个)
*/
@PostMapping("/upload")
public AjaxResult uploadFile(MultipartFile file) throws Exception
{
try
{
// 上传文件路径
String filePath = RuoYiConfig.getUploadPath();
// 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
String url = serverConfig.getUrl() + fileName;
AjaxResult ajax = AjaxResult.success();
ajax.put("url", url);
ajax.put("fileName", fileName);
ajax.put("newFileName", FileUtils.getName(fileName));
ajax.put("originalFilename", file.getOriginalFilename());
return ajax;
}
catch (Exception e)
{
return AjaxResult.error(e.getMessage());
}
}
/**
* 通用上传请求(多个)
*/
@PostMapping("/uploads")
public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
{
try
{
// 上传文件路径
String filePath = RuoYiConfig.getUploadPath();
List<String> urls = new ArrayList<String>();
List<String> fileNames = new ArrayList<String>();
List<String> newFileNames = new ArrayList<String>();
List<String> originalFilenames = new ArrayList<String>();
for (MultipartFile file : files)
{
// 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
String url = serverConfig.getUrl() + fileName;
urls.add(url);
fileNames.add(fileName);
newFileNames.add(FileUtils.getName(fileName));
originalFilenames.add(file.getOriginalFilename());
}
AjaxResult ajax = AjaxResult.success();
ajax.put("urls", StringUtils.join(urls, FILE_DELIMITER));
ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMITER));
ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMITER));
ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMITER));
return ajax;
}
catch (Exception e)
{
return AjaxResult.error(e.getMessage());
}
}
/**
* 本地资源通用下载
*/
@GetMapping("/download/resource")
public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
throws Exception
{
try
{
if (!FileUtils.checkAllowDownload(resource))
{
throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
}
// 本地资源路径
String localPath = RuoYiConfig.getProfile();
// 数据库资源地址
String downloadPath = localPath + FileUtils.stripPrefix(resource);
// 下载名称
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, downloadName);
FileUtils.writeBytes(downloadPath, response.getOutputStream());
}
catch (Exception e)
{
log.error("下载文件失败", e);
}
}
}
@@ -0,0 +1,170 @@
package com.ruoyi.web.controller.common;
import java.nio.charset.StandardCharsets;
import java.io.InputStream;
import java.net.URI;
import java.net.URLConnection;
import java.util.Date;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.config.RuoYiConfig.OssProperties;
import com.ruoyi.common.core.domain.AjaxResult;
/**
* 阿里云 OSS 签名服务
*
* 用于前端 <el-upload> 直传 OSS: 前端先 GET /common/oss/sign?dir=xxx
* 拿到 {host, dir, accessKeyId, policy, signature} 后直接 POST 到 OSS,
* 不再走后端中转. secretKey 不下发到前端.
*
* 配置项 (ruoyi.oss.*):
* enabled: 是否启用 OSS (false 时返回空, 前端 fallback 到 /common/upload 本地存储)
* endpoint: https://<bucket>.oss-cn-beijing.aliyuncs.com
* bucket: bucket 名称
* accessKeyId: AK
* accessKeySecret: SK (仅后端使用)
* dirPrefix: 上传目录前缀, 默认 "ry8080/"
* expireSeconds: 签名失效时间, 默认 3600
*/
@RestController
@RequestMapping("/common/oss")
public class OssController
{
@org.springframework.beans.factory.annotation.Autowired
private RuoYiConfig ruoyiConfig;
@GetMapping("/sign")
public AjaxResult sign(String dir)
{
OssProperties props = ruoyiConfig.getOss();
if (props == null || !props.isEnabled())
{
return AjaxResult.error("OSS 未启用 (ruoyi.oss.enabled=false)");
}
if (dir == null || dir.isEmpty())
{
dir = props.getDirPrefix();
}
// 不允许目录穿越
if (dir.contains(".."))
{
return AjaxResult.error("非法目录");
}
long expire = props.getExpireSeconds() * 1000L;
Date expiration = new Date(System.currentTimeMillis() + expire);
// OSS PostObject policy 文档: https://help.aliyun.com/document_detail/31988.html
// expiration 格式: yyyy-MM-ddTHH:mm:ss.SSSZ (OSS 严格解析, 毫秒必须 3 位)
// 注: OSS conditions 是 AND 关系, 不支持 OR 嵌套; Content-Type 不在 policy 中限制,
// 由前端 FormData 字段 'Content-Type' 携带, OSS 按此存文件元数据
String policyText = "{\"expiration\":\"" + toISO8601(expiration)
+ "\",\"conditions\":["
+ "[\"content-length-range\",0,104857600],"
+ "[\"starts-with\",\"$key\",\"" + dir + "\"]"
+ "]}";
String policyBase64 = java.util.Base64.getEncoder().encodeToString(
policyText.getBytes(StandardCharsets.UTF_8));
String signature = hmacSha1Base64(props.getAccessKeySecret(), policyBase64);
AjaxResult ajax = AjaxResult.success();
ajax.put("host", props.getEndpoint());
ajax.put("dir", dir);
ajax.put("accessKeyId", props.getAccessKeyId());
ajax.put("policy", policyBase64);
ajax.put("signature", signature);
ajax.put("expire", expiration.getTime());
return ajax;
}
/** OSS 期望 ISO8601 (yyyy-MM-ddTHH:mm:ss.SSS'Z') GMT 时间 */
private static String toISO8601(Date d)
{
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
return sdf.format(d);
}
private static String hmacSha1Base64(String key, String data)
{
try
{
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA1"));
byte[] bytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
return java.util.Base64.getEncoder().encodeToString(bytes);
}
catch (Exception e)
{
throw new RuntimeException("OSS 签名失败", e);
}
}
/**
* OSS 文件代理: OSS bucket 设置了 Content-Disposition: attachment,
* 直接 iframe/embed 会被强制下载. 此接口转发 OSS 字节流并重写 header,
* 让浏览器内嵌预览 (PDF/图片).
* 公开访问, 无需 token (SecurityConfig 已对 /common/oss/** 公开).
*
* @param url 完整 OSS URL (前端从 biz_project.invitationUrl 等字段拿到)
*/
@GetMapping("/proxy")
public void ossProxy(@RequestParam String url, HttpServletResponse response) throws Exception
{
// 安全: 仅允许代理 hwtossbamlorgcn bucket (防止 SSRF 攻击)
if (url == null || !url.contains("hwtossbamlorgcn.oss-cn-beijing.aliyuncs.com"))
{
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
return;
}
URI uri = URI.create(url);
URLConnection conn = uri.toURL().openConnection();
conn.setConnectTimeout(10000);
conn.setReadTimeout(30000);
String origCt = conn.getContentType();
String path = uri.getPath();
String filename = path.substring(path.lastIndexOf('/') + 1);
// 重写 Content-Type: OSS 可能返回 octet-stream, 按扩展名强制给正确 mime
String ct = origCt;
if (ct == null || ct.contains("octet-stream") || ct.isEmpty())
{
String lower = filename.toLowerCase();
if (lower.endsWith(".pdf")) ct = "application/pdf";
else if (lower.endsWith(".png")) ct = "image/png";
else if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) ct = "image/jpeg";
else if (lower.endsWith(".gif")) ct = "image/gif";
else if (lower.endsWith(".webp")) ct = "image/webp";
else ct = origCt != null ? origCt : "application/octet-stream";
}
// 关键: 重写 Content-Disposition 为 inline (OSS 默认是 attachment)
response.setContentType(ct);
response.setHeader("Content-Disposition", "inline; filename=\"" + filename + "\"");
response.setHeader("Cache-Control", "public, max-age=3600");
try (InputStream in = conn.getInputStream())
{
byte[] buf = new byte[8192];
int n;
while ((n = in.read(buf)) > 0)
{
response.getOutputStream().write(buf, 0, n);
}
}
catch (java.io.FileNotFoundException e)
{
// OSS 返回 404 (文件不存在) - 返回 404 而非 500 + application/json
// 避免前端 embed 拿到 JSON 后误渲染
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.setContentType("text/plain;charset=utf-8");
response.getWriter().write("FILE_NOT_FOUND");
}
}
}
@@ -0,0 +1,122 @@
package com.ruoyi.web.controller.monitor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysCache;
/**
* 缓存监控
*
* @author ruoyi
*/
@RestController
@RequestMapping("/monitor/cache")
public class CacheController
{
@Autowired
private RedisTemplate<String, String> redisTemplate;
private final static List<SysCache> caches = new ArrayList<SysCache>();
{
caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息"));
caches.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "配置信息"));
caches.add(new SysCache(CacheConstants.SYS_DICT_KEY, "数据字典"));
caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码"));
caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "防重提交"));
caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "限流处理"));
caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密码错误次数"));
}
@SuppressWarnings("deprecation")
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@GetMapping()
public AjaxResult getInfo() throws Exception
{
Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
Map<String, Object> result = new HashMap<>(3);
result.put("info", info);
result.put("dbSize", dbSize);
List<Map<String, String>> pieList = new ArrayList<>();
commandStats.stringPropertyNames().forEach(key -> {
Map<String, String> data = new HashMap<>(2);
String property = commandStats.getProperty(key);
data.put("name", StringUtils.removeStart(key, "cmdstat_"));
data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
pieList.add(data);
});
result.put("commandStats", pieList);
return AjaxResult.success(result);
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@GetMapping("/getNames")
public AjaxResult cache()
{
return AjaxResult.success(caches);
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@GetMapping("/getKeys/{cacheName}")
public AjaxResult getCacheKeys(@PathVariable String cacheName)
{
Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
return AjaxResult.success(new TreeSet<>(cacheKeys));
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@GetMapping("/getValue/{cacheName}/{cacheKey}")
public AjaxResult getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey)
{
String cacheValue = redisTemplate.opsForValue().get(cacheKey);
SysCache sysCache = new SysCache(cacheName, cacheKey, cacheValue);
return AjaxResult.success(sysCache);
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@DeleteMapping("/clearCacheName/{cacheName}")
public AjaxResult clearCacheName(@PathVariable String cacheName)
{
Collection<String> cacheKeys = redisTemplate.keys(cacheName + "*");
redisTemplate.delete(cacheKeys);
return AjaxResult.success();
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@DeleteMapping("/clearCacheKey/{cacheKey}")
public AjaxResult clearCacheKey(@PathVariable String cacheKey)
{
redisTemplate.delete(cacheKey);
return AjaxResult.success();
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@DeleteMapping("/clearCacheAll")
public AjaxResult clearCacheAll()
{
Collection<String> cacheKeys = redisTemplate.keys("*");
redisTemplate.delete(cacheKeys);
return AjaxResult.success();
}
}
@@ -0,0 +1,27 @@
package com.ruoyi.web.controller.monitor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.framework.web.domain.Server;
/**
* 服务器监控
*
* @author ruoyi
*/
@RestController
@RequestMapping("/monitor/server")
public class ServerController
{
@PreAuthorize("@ss.hasPermi('monitor:server:list')")
@GetMapping()
public AjaxResult getInfo() throws Exception
{
Server server = new Server();
server.copyTo();
return AjaxResult.success(server);
}
}
@@ -0,0 +1,82 @@
package com.ruoyi.web.controller.monitor;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPasswordService;
import com.ruoyi.system.domain.SysLogininfor;
import com.ruoyi.system.service.ISysLogininforService;
/**
* 系统访问记录
*
* @author ruoyi
*/
@RestController
@RequestMapping("/monitor/logininfor")
public class SysLogininforController extends BaseController
{
@Autowired
private ISysLogininforService logininforService;
@Autowired
private SysPasswordService passwordService;
@PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
@GetMapping("/list")
public TableDataInfo list(SysLogininfor logininfor)
{
startPage();
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
return getDataTable(list);
}
@Log(title = "登录日志", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
@PostMapping("/export")
public void export(HttpServletResponse response, SysLogininfor logininfor)
{
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
util.exportExcel(response, list, "登录日志");
}
@PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
@Log(title = "登录日志", businessType = BusinessType.DELETE)
@DeleteMapping("/{infoIds}")
public AjaxResult remove(@PathVariable Long[] infoIds)
{
return toAjax(logininforService.deleteLogininforByIds(infoIds));
}
@PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
@Log(title = "登录日志", businessType = BusinessType.CLEAN)
@DeleteMapping("/clean")
public AjaxResult clean()
{
logininforService.cleanLogininfor();
return success();
}
@PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')")
@Log(title = "账户解锁", businessType = BusinessType.OTHER)
@GetMapping("/unlock/{userName}")
public AjaxResult unlock(@PathVariable("userName") String userName)
{
passwordService.clearLoginRecordCache(userName);
return success();
}
}
@@ -0,0 +1,69 @@
package com.ruoyi.web.controller.monitor;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysOperLog;
import com.ruoyi.system.service.ISysOperLogService;
/**
* 操作日志记录
*
* @author ruoyi
*/
@RestController
@RequestMapping("/monitor/operlog")
public class SysOperlogController extends BaseController
{
@Autowired
private ISysOperLogService operLogService;
@PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
@GetMapping("/list")
public TableDataInfo list(SysOperLog operLog)
{
startPage();
List<SysOperLog> list = operLogService.selectOperLogList(operLog);
return getDataTable(list);
}
@Log(title = "操作日志", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
@PostMapping("/export")
public void export(HttpServletResponse response, SysOperLog operLog)
{
List<SysOperLog> list = operLogService.selectOperLogList(operLog);
ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
util.exportExcel(response, list, "操作日志");
}
@Log(title = "操作日志", businessType = BusinessType.DELETE)
@PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
@DeleteMapping("/{operIds}")
public AjaxResult remove(@PathVariable Long[] operIds)
{
return toAjax(operLogService.deleteOperLogByIds(operIds));
}
@Log(title = "操作日志", businessType = BusinessType.CLEAN)
@PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
@DeleteMapping("/clean")
public AjaxResult clean()
{
operLogService.cleanOperLog();
return success();
}
}
@@ -0,0 +1,83 @@
package com.ruoyi.web.controller.monitor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysUserOnline;
import com.ruoyi.system.service.ISysUserOnlineService;
/**
* 在线用户监控
*
* @author ruoyi
*/
@RestController
@RequestMapping("/monitor/online")
public class SysUserOnlineController extends BaseController
{
@Autowired
private ISysUserOnlineService userOnlineService;
@Autowired
private RedisCache redisCache;
@PreAuthorize("@ss.hasPermi('monitor:online:list')")
@GetMapping("/list")
public TableDataInfo list(String ipaddr, String userName)
{
Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
for (String key : keys)
{
LoginUser user = redisCache.getCacheObject(key);
if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
{
userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
}
else if (StringUtils.isNotEmpty(ipaddr))
{
userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
}
else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
{
userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
}
else
{
userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
}
}
Collections.reverse(userOnlineList);
userOnlineList.removeAll(Collections.singleton(null));
return getDataTable(userOnlineList);
}
/**
* 强退用户
*/
@PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
@Log(title = "在线用户", businessType = BusinessType.FORCE)
@DeleteMapping("/{tokenId}")
public AjaxResult forceLogout(@PathVariable String tokenId)
{
redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
return success();
}
}
@@ -0,0 +1,133 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.service.ISysConfigService;
/**
* 参数配置 信息操作处理
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/config")
public class SysConfigController extends BaseController
{
@Autowired
private ISysConfigService configService;
/**
* 获取参数配置列表
*/
@PreAuthorize("@ss.hasPermi('system:config:list')")
@GetMapping("/list")
public TableDataInfo list(SysConfig config)
{
startPage();
List<SysConfig> list = configService.selectConfigList(config);
return getDataTable(list);
}
@Log(title = "参数管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:config:export')")
@PostMapping("/export")
public void export(HttpServletResponse response, SysConfig config)
{
List<SysConfig> list = configService.selectConfigList(config);
ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
util.exportExcel(response, list, "参数数据");
}
/**
* 根据参数编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:config:query')")
@GetMapping(value = "/{configId}")
public AjaxResult getInfo(@PathVariable Long configId)
{
return success(configService.selectConfigById(configId));
}
/**
* 根据参数键名查询参数值
*/
@GetMapping(value = "/configKey/{configKey}")
public AjaxResult getConfigKey(@PathVariable String configKey)
{
return success(configService.selectConfigByKey(configKey));
}
/**
* 新增参数配置
*/
@PreAuthorize("@ss.hasPermi('system:config:add')")
@Log(title = "参数管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysConfig config)
{
if (!configService.checkConfigKeyUnique(config))
{
return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
}
config.setCreateBy(getUsername());
return toAjax(configService.insertConfig(config));
}
/**
* 修改参数配置
*/
@PreAuthorize("@ss.hasPermi('system:config:edit')")
@Log(title = "参数管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysConfig config)
{
if (!configService.checkConfigKeyUnique(config))
{
return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
}
config.setUpdateBy(getUsername());
return toAjax(configService.updateConfig(config));
}
/**
* 删除参数配置
*/
@PreAuthorize("@ss.hasPermi('system:config:remove')")
@Log(title = "参数管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{configIds}")
public AjaxResult remove(@PathVariable Long[] configIds)
{
configService.deleteConfigByIds(configIds);
return success();
}
/**
* 刷新参数缓存
*/
@PreAuthorize("@ss.hasPermi('system:config:remove')")
@Log(title = "参数管理", businessType = BusinessType.CLEAN)
@DeleteMapping("/refreshCache")
public AjaxResult refreshCache()
{
configService.resetConfigCache();
return success();
}
}
@@ -0,0 +1,147 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysDeptService;
/**
* 部门信息
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/dept")
public class SysDeptController extends BaseController
{
@Autowired
private ISysDeptService deptService;
/**
* 获取部门列表
*/
@PreAuthorize("@ss.hasPermi('system:dept:list')")
@GetMapping("/list")
public AjaxResult list(SysDept dept)
{
List<SysDept> depts = deptService.selectDeptList(dept);
return success(depts);
}
/**
* 查询部门列表(排除节点)
*/
@PreAuthorize("@ss.hasPermi('system:dept:list')")
@GetMapping("/list/exclude/{deptId}")
public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
{
List<SysDept> depts = deptService.selectDeptList(new SysDept());
depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
return success(depts);
}
/**
* 根据部门编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:dept:query')")
@GetMapping(value = "/{deptId}")
public AjaxResult getInfo(@PathVariable Long deptId)
{
deptService.checkDeptDataScope(deptId);
return success(deptService.selectDeptById(deptId));
}
/**
* 新增部门
*/
@PreAuthorize("@ss.hasPermi('system:dept:add')")
@Log(title = "部门管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysDept dept)
{
if (!deptService.checkDeptNameUnique(dept))
{
return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
}
dept.setCreateBy(getUsername());
return toAjax(deptService.insertDept(dept));
}
/**
* 修改部门
*/
@PreAuthorize("@ss.hasPermi('system:dept:edit')")
@Log(title = "部门管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysDept dept)
{
Long deptId = dept.getDeptId();
deptService.checkDeptDataScope(deptId);
if (!deptService.checkDeptNameUnique(dept))
{
return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
}
else if (dept.getParentId().equals(deptId))
{
return error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
}
else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0)
{
return error("该部门包含未停用的子部门!");
}
dept.setUpdateBy(getUsername());
return toAjax(deptService.updateDept(dept));
}
/**
* 保存部门排序
*/
@PreAuthorize("@ss.hasPermi('system:dept:edit')")
@Log(title = "保存部门排序", businessType = BusinessType.UPDATE)
@PutMapping("/updateSort")
public AjaxResult updateSort(@RequestBody Map<String, String> params)
{
String[] deptIds = params.get("deptIds").split(",");
String[] orderNums = params.get("orderNums").split(",");
deptService.updateDeptSort(deptIds, orderNums);
return success();
}
/**
* 删除部门
*/
@PreAuthorize("@ss.hasPermi('system:dept:remove')")
@Log(title = "部门管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{deptId}")
public AjaxResult remove(@PathVariable Long deptId)
{
if (deptService.hasChildByDeptId(deptId))
{
return warn("存在下级部门,不允许删除");
}
if (deptService.checkDeptExistUser(deptId))
{
return warn("部门存在用户,不允许删除");
}
deptService.checkDeptDataScope(deptId);
return toAjax(deptService.deleteDeptById(deptId));
}
}
@@ -0,0 +1,121 @@
package com.ruoyi.web.controller.system;
import java.util.ArrayList;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysDictTypeService;
/**
* 数据字典信息
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/dict/data")
public class SysDictDataController extends BaseController
{
@Autowired
private ISysDictDataService dictDataService;
@Autowired
private ISysDictTypeService dictTypeService;
@PreAuthorize("@ss.hasPermi('system:dict:list')")
@GetMapping("/list")
public TableDataInfo list(SysDictData dictData)
{
startPage();
List<SysDictData> list = dictDataService.selectDictDataList(dictData);
return getDataTable(list);
}
@Log(title = "字典数据", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:dict:export')")
@PostMapping("/export")
public void export(HttpServletResponse response, SysDictData dictData)
{
List<SysDictData> list = dictDataService.selectDictDataList(dictData);
ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class);
util.exportExcel(response, list, "字典数据");
}
/**
* 查询字典数据详细
*/
@PreAuthorize("@ss.hasPermi('system:dict:query')")
@GetMapping(value = "/{dictCode}")
public AjaxResult getInfo(@PathVariable Long dictCode)
{
return success(dictDataService.selectDictDataById(dictCode));
}
/**
* 根据字典类型查询字典数据信息
*/
@GetMapping(value = "/type/{dictType}")
public AjaxResult dictType(@PathVariable String dictType)
{
List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
if (StringUtils.isNull(data))
{
data = new ArrayList<SysDictData>();
}
return success(data);
}
/**
* 新增字典类型
*/
@PreAuthorize("@ss.hasPermi('system:dict:add')")
@Log(title = "字典数据", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysDictData dict)
{
dict.setCreateBy(getUsername());
return toAjax(dictDataService.insertDictData(dict));
}
/**
* 修改保存字典类型
*/
@PreAuthorize("@ss.hasPermi('system:dict:edit')")
@Log(title = "字典数据", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysDictData dict)
{
dict.setUpdateBy(getUsername());
return toAjax(dictDataService.updateDictData(dict));
}
/**
* 删除字典类型
*/
@PreAuthorize("@ss.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.DELETE)
@DeleteMapping("/{dictCodes}")
public AjaxResult remove(@PathVariable Long[] dictCodes)
{
dictDataService.deleteDictDataByIds(dictCodes);
return success();
}
}
@@ -0,0 +1,131 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictType;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDictTypeService;
/**
* 数据字典信息
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/dict/type")
public class SysDictTypeController extends BaseController
{
@Autowired
private ISysDictTypeService dictTypeService;
@PreAuthorize("@ss.hasPermi('system:dict:list')")
@GetMapping("/list")
public TableDataInfo list(SysDictType dictType)
{
startPage();
List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
return getDataTable(list);
}
@Log(title = "字典类型", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:dict:export')")
@PostMapping("/export")
public void export(HttpServletResponse response, SysDictType dictType)
{
List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class);
util.exportExcel(response, list, "字典类型");
}
/**
* 查询字典类型详细
*/
@PreAuthorize("@ss.hasPermi('system:dict:query')")
@GetMapping(value = "/{dictId}")
public AjaxResult getInfo(@PathVariable Long dictId)
{
return success(dictTypeService.selectDictTypeById(dictId));
}
/**
* 新增字典类型
*/
@PreAuthorize("@ss.hasPermi('system:dict:add')")
@Log(title = "字典类型", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysDictType dict)
{
if (!dictTypeService.checkDictTypeUnique(dict))
{
return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
}
dict.setCreateBy(getUsername());
return toAjax(dictTypeService.insertDictType(dict));
}
/**
* 修改字典类型
*/
@PreAuthorize("@ss.hasPermi('system:dict:edit')")
@Log(title = "字典类型", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysDictType dict)
{
if (!dictTypeService.checkDictTypeUnique(dict))
{
return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
}
dict.setUpdateBy(getUsername());
return toAjax(dictTypeService.updateDictType(dict));
}
/**
* 删除字典类型
*/
@PreAuthorize("@ss.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.DELETE)
@DeleteMapping("/{dictIds}")
public AjaxResult remove(@PathVariable Long[] dictIds)
{
dictTypeService.deleteDictTypeByIds(dictIds);
return success();
}
/**
* 刷新字典缓存
*/
@PreAuthorize("@ss.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.CLEAN)
@DeleteMapping("/refreshCache")
public AjaxResult refreshCache()
{
dictTypeService.resetDictCache();
return success();
}
/**
* 获取字典选择框列表
*/
@GetMapping("/optionselect")
public AjaxResult optionselect()
{
List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
return success(dictTypes);
}
}
@@ -0,0 +1,64 @@
package com.ruoyi.web.controller.system;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysUserService;
/**
* 首页
*
* @author ruoyi
*/
@RestController
public class SysIndexController
{
/** 系统基础配置 */
@Autowired
private RuoYiConfig ruoyiConfig;
@Autowired
private ISysUserService userService;
/**
* 访问首页,提示语
*/
@RequestMapping("/")
public String index()
{
return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
}
/**
* 解锁屏幕
*/
@PostMapping("/unlockscreen")
public AjaxResult unlockScreen(@RequestBody Map<String, String> body)
{
String password = body.get("password");
if (StringUtils.isEmpty(password))
{
return AjaxResult.error("密码不能为空");
}
String username = SecurityUtils.getUsername();
SysUser user = userService.selectUserByUserName(username);
if (user == null)
{
return AjaxResult.error("服务器超时,请重新登录");
}
if (!SecurityUtils.matchesPassword(password, user.getPassword()))
{
return AjaxResult.error("密码错误,请重新输入");
}
return AjaxResult.success("解锁成功");
}
}
@@ -0,0 +1,138 @@
package com.ruoyi.web.controller.system;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysMenuService;
/**
* 登录验证
*
* @author ruoyi
*/
@RestController
public class SysLoginController
{
@Autowired
private SysLoginService loginService;
@Autowired
private ISysMenuService menuService;
@Autowired
private SysPermissionService permissionService;
@Autowired
private TokenService tokenService;
@Autowired
private ISysConfigService configService;
/**
* 登录方法
*
* @param loginBody 登录信息
* @return 结果
*/
@PostMapping("/login")
public AjaxResult login(@RequestBody LoginBody loginBody)
{
AjaxResult ajax = AjaxResult.success();
// 生成令牌
String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
loginBody.getUuid());
ajax.put(Constants.TOKEN, token);
return ajax;
}
/**
* 获取用户信息
*
* @return 用户信息
*/
@GetMapping("getInfo")
public AjaxResult getInfo()
{
LoginUser loginUser = SecurityUtils.getLoginUser();
SysUser user = loginUser.getUser();
// 角色集合
Set<String> roles = permissionService.getRolePermission(user);
// 权限集合
Set<String> permissions = permissionService.getMenuPermission(user);
if (!loginUser.getPermissions().equals(permissions))
{
loginUser.setPermissions(permissions);
tokenService.refreshToken(loginUser);
}
AjaxResult ajax = AjaxResult.success();
ajax.put("user", user);
ajax.put("roles", roles);
ajax.put("permissions", permissions);
ajax.put("pwdChrtype", getSysAccountChrtype());
ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
return ajax;
}
/**
* 获取路由信息
*
* @return 路由信息
*/
@GetMapping("getRouters")
public AjaxResult getRouters()
{
Long userId = SecurityUtils.getUserId();
List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
return AjaxResult.success(menuService.buildMenus(menus));
}
// 获取用户密码自定义配置规则
public String getSysAccountChrtype()
{
return Convert.toStr(configService.selectConfigByKey("sys.account.chrtype"), "0");
}
// 检查初始密码是否提醒修改
public boolean initPasswordIsModify(Date pwdUpdateDate)
{
Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
}
// 检查密码是否过期
public boolean passwordIsExpiration(Date pwdUpdateDate)
{
Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
if (passwordValidateDays != null && passwordValidateDays > 0)
{
if (StringUtils.isNull(pwdUpdateDate))
{
// 如果从未修改过初始密码,直接提醒过期
return true;
}
Date nowDate = DateUtils.getNowDate();
return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
}
return false;
}
}
@@ -0,0 +1,165 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysMenuService;
/**
* 菜单信息
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/menu")
public class SysMenuController extends BaseController
{
@Autowired
private ISysMenuService menuService;
/**
* 获取菜单列表
*/
@PreAuthorize("@ss.hasPermi('system:menu:list')")
@GetMapping("/list")
public AjaxResult list(SysMenu menu)
{
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
return success(menus);
}
/**
* 根据菜单编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:menu:query')")
@GetMapping(value = "/{menuId}")
public AjaxResult getInfo(@PathVariable Long menuId)
{
return success(menuService.selectMenuById(menuId));
}
/**
* 获取菜单下拉树列表
*/
@GetMapping("/treeselect")
public AjaxResult treeselect(SysMenu menu)
{
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
return success(menuService.buildMenuTreeSelect(menus));
}
/**
* 加载对应角色菜单列表树
*/
@GetMapping(value = "/roleMenuTreeselect/{roleId}")
public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
{
List<SysMenu> menus = menuService.selectMenuList(getUserId());
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
ajax.put("menus", menuService.buildMenuTreeSelect(menus));
return ajax;
}
/**
* 新增菜单
*/
@PreAuthorize("@ss.hasPermi('system:menu:add')")
@Log(title = "菜单管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysMenu menu)
{
if (!menuService.checkMenuNameUnique(menu))
{
return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
}
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
{
return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
}
else if (!menuService.checkRouteConfigUnique(menu))
{
return error("新增菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
}
menu.setCreateBy(getUsername());
return toAjax(menuService.insertMenu(menu));
}
/**
* 修改菜单
*/
@PreAuthorize("@ss.hasPermi('system:menu:edit')")
@Log(title = "菜单管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysMenu menu)
{
if (!menuService.checkMenuNameUnique(menu))
{
return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
}
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
{
return error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
}
else if (menu.getMenuId().equals(menu.getParentId()))
{
return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
}
else if (!menuService.checkRouteConfigUnique(menu))
{
return error("修改菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
}
menu.setUpdateBy(getUsername());
return toAjax(menuService.updateMenu(menu));
}
/**
* 保存菜单排序
*/
@PreAuthorize("@ss.hasPermi('system:menu:edit')")
@Log(title = "保存菜单排序", businessType = BusinessType.UPDATE)
@PutMapping("/updateSort")
public AjaxResult updateSort(@RequestBody Map<String, String> params)
{
String[] menuIds = params.get("menuIds").split(",");
String[] orderNums = params.get("orderNums").split(",");
menuService.updateMenuSort(menuIds, orderNums);
return success();
}
/**
* 删除菜单
*/
@PreAuthorize("@ss.hasPermi('system:menu:remove')")
@Log(title = "菜单管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{menuId}")
public AjaxResult remove(@PathVariable("menuId") Long menuId)
{
if (menuService.hasChildByMenuId(menuId))
{
return warn("存在子菜单,不允许删除");
}
if (menuService.checkMenuExistRole(menuId))
{
return warn("菜单已分配,不允许删除");
}
return toAjax(menuService.deleteMenuById(menuId));
}
}
@@ -0,0 +1,150 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.service.ISysNoticeReadService;
import com.ruoyi.system.service.ISysNoticeService;
/**
* 公告 信息操作处理
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/notice")
public class SysNoticeController extends BaseController
{
@Autowired
private ISysNoticeService noticeService;
@Autowired
private ISysNoticeReadService noticeReadService;
/**
* 获取通知公告列表
*/
@PreAuthorize("@ss.hasPermi('system:notice:list')")
@GetMapping("/list")
public TableDataInfo list(SysNotice notice)
{
startPage();
List<SysNotice> list = noticeService.selectNoticeList(notice);
return getDataTable(list);
}
/**
* 根据通知公告编号获取详细信息
*/
@GetMapping(value = "/{noticeId}")
public AjaxResult getInfo(@PathVariable Long noticeId)
{
return success(noticeService.selectNoticeById(noticeId));
}
/**
* 新增通知公告
*/
@PreAuthorize("@ss.hasPermi('system:notice:add')")
@Log(title = "通知公告", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysNotice notice)
{
notice.setCreateBy(getUsername());
return toAjax(noticeService.insertNotice(notice));
}
/**
* 修改通知公告
*/
@PreAuthorize("@ss.hasPermi('system:notice:edit')")
@Log(title = "通知公告", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysNotice notice)
{
notice.setUpdateBy(getUsername());
return toAjax(noticeService.updateNotice(notice));
}
/**
* 首页顶部公告列表(返回全部正常公告,带当前用户已读标记,最多5条)
*/
@GetMapping("/listTop")
@ResponseBody
public AjaxResult listTop()
{
Long userId = getUserId();
List<SysNotice> list = noticeReadService.selectNoticeListWithReadStatus(userId, 5);
long unreadCount = list.stream().filter(n -> !n.getIsRead()).count();
AjaxResult result = AjaxResult.success(list);
result.put("unreadCount", unreadCount);
return result;
}
/**
* 标记公告已读
*/
@PostMapping("/markRead")
@ResponseBody
public AjaxResult markRead(Long noticeId)
{
Long userId = getUserId();
noticeReadService.markRead(noticeId, userId);
return success();
}
/**
* 批量标记已读
*/
@PostMapping("/markReadAll")
@ResponseBody
public AjaxResult markReadAll(String ids)
{
Long userId = getUserId();
Long[] noticeIds = Convert.toLongArray(ids);
noticeReadService.markReadBatch(userId, noticeIds);
return success();
}
/**
* 已读用户列表数据
*/
@PreAuthorize("@ss.hasPermi('system:notice:list')")
@GetMapping("/readUsers/list")
@ResponseBody
public TableDataInfo readUsersList(Long noticeId, String searchValue)
{
startPage();
List<?> list = noticeReadService.selectReadUsersByNoticeId(noticeId, searchValue);
return getDataTable(list);
}
/**
* 删除通知公告
*/
@PreAuthorize("@ss.hasPermi('system:notice:remove')")
@Log(title = "通知公告", businessType = BusinessType.DELETE)
@DeleteMapping("/{noticeIds}")
public AjaxResult remove(@PathVariable Long[] noticeIds)
{
noticeReadService.deleteByNoticeIds(noticeIds);
return toAjax(noticeService.deleteNoticeByIds(noticeIds));
}
}
@@ -0,0 +1,129 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.service.ISysPostService;
/**
* 岗位信息操作处理
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/post")
public class SysPostController extends BaseController
{
@Autowired
private ISysPostService postService;
/**
* 获取岗位列表
*/
@PreAuthorize("@ss.hasPermi('system:post:list')")
@GetMapping("/list")
public TableDataInfo list(SysPost post)
{
startPage();
List<SysPost> list = postService.selectPostList(post);
return getDataTable(list);
}
@Log(title = "岗位管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:post:export')")
@PostMapping("/export")
public void export(HttpServletResponse response, SysPost post)
{
List<SysPost> list = postService.selectPostList(post);
ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class);
util.exportExcel(response, list, "岗位数据");
}
/**
* 根据岗位编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:post:query')")
@GetMapping(value = "/{postId}")
public AjaxResult getInfo(@PathVariable Long postId)
{
return success(postService.selectPostById(postId));
}
/**
* 新增岗位
*/
@PreAuthorize("@ss.hasPermi('system:post:add')")
@Log(title = "岗位管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysPost post)
{
if (!postService.checkPostNameUnique(post))
{
return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
}
else if (!postService.checkPostCodeUnique(post))
{
return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
}
post.setCreateBy(getUsername());
return toAjax(postService.insertPost(post));
}
/**
* 修改岗位
*/
@PreAuthorize("@ss.hasPermi('system:post:edit')")
@Log(title = "岗位管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysPost post)
{
if (!postService.checkPostNameUnique(post))
{
return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
}
else if (!postService.checkPostCodeUnique(post))
{
return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
}
post.setUpdateBy(getUsername());
return toAjax(postService.updatePost(post));
}
/**
* 删除岗位
*/
@PreAuthorize("@ss.hasPermi('system:post:remove')")
@Log(title = "岗位管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{postIds}")
public AjaxResult remove(@PathVariable Long[] postIds)
{
return toAjax(postService.deletePostByIds(postIds));
}
/**
* 获取岗位选择框列表
*/
@GetMapping("/optionselect")
public AjaxResult optionselect()
{
List<SysPost> posts = postService.selectPostAll();
return success(posts);
}
}
@@ -0,0 +1,216 @@
package com.ruoyi.web.controller.system;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.business.dto.SmsValidForm;
import com.ruoyi.business.service.SysSmsService;
/**
* 个人信息 业务处理
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/user/profile")
public class SysProfileController extends BaseController
{
@Autowired
private ISysUserService userService;
@Autowired
private TokenService tokenService;
@Autowired
private SysSmsService smsService;
/**
* 个人信息
*/
@GetMapping
public AjaxResult profile()
{
LoginUser loginUser = getLoginUser();
SysUser user = loginUser.getUser();
AjaxResult ajax = AjaxResult.success(user);
ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
return ajax;
}
/**
* 修改用户
*/
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult updateProfile(@RequestBody SysUser user)
{
LoginUser loginUser = getLoginUser();
SysUser currentUser = loginUser.getUser();
currentUser.setNickName(user.getNickName());
currentUser.setEmail(user.getEmail());
currentUser.setPhonenumber(user.getPhonenumber());
currentUser.setSex(user.getSex());
if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
{
return error("修改用户'" + loginUser.getUsername() + "'失败,手机号码已存在");
}
if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
{
return error("修改用户'" + loginUser.getUsername() + "'失败,邮箱账号已存在");
}
if (userService.updateUserProfile(currentUser) > 0)
{
// 更新缓存用户信息
tokenService.setLoginUser(loginUser);
return success();
}
return error("修改个人信息异常,请联系管理员");
}
/**
* 重置密码
*/
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PutMapping("/updatePwd")
public AjaxResult updatePwd(@RequestBody Map<String, String> params)
{
String oldPassword = params.get("oldPassword");
String newPassword = params.get("newPassword");
LoginUser loginUser = getLoginUser();
Long userId = loginUser.getUserId();
SysUser user = userService.selectUserById(userId);
String password = user.getPassword();
if (!SecurityUtils.matchesPassword(oldPassword, password))
{
return error("修改密码失败,旧密码错误");
}
if (SecurityUtils.matchesPassword(newPassword, password))
{
return error("新密码不能与旧密码相同");
}
newPassword = SecurityUtils.encryptPassword(newPassword);
if (userService.resetUserPwd(userId, newPassword) > 0)
{
// 更新缓存用户密码&密码最后更新时间
loginUser.getUser().setPwdUpdateDate(DateUtils.getNowDate());
loginUser.getUser().setPassword(newPassword);
tokenService.setLoginUser(loginUser);
return success();
}
return error("修改密码异常,请联系管理员");
}
/**
* 修改手机号 (需短信验证码)
* 参数: { phone, smsCode, uuid }
*/
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PostMapping("/changePhone")
public AjaxResult changePhone(@RequestBody SmsValidForm form)
{
if (StringUtils.isEmpty(form.getPhone()) || StringUtils.isEmpty(form.getSmsCode()) || StringUtils.isEmpty(form.getUuid()))
{
return error("参数不完整");
}
// 1. 校验短信验证码
try
{
smsService.verifyCode(form);
}
catch (RuntimeException e)
{
return error(e.getMessage());
}
// 2. 更新当前用户手机号
LoginUser loginUser = getLoginUser();
SysUser currentUser = loginUser.getUser();
currentUser.setPhonenumber(form.getPhone());
if (!userService.checkPhoneUnique(currentUser))
{
return error("手机号码已被占用");
}
if (userService.updateUserProfile(currentUser) > 0)
{
// 同步缓存
tokenService.setLoginUser(loginUser);
return success();
}
return error("修改手机号失败");
}
/**
* 头像上传 (本地, RuoYi 默认)
*/
@Log(title = "用户头像", businessType = BusinessType.UPDATE)
@PostMapping("/avatar")
public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception
{
if (!file.isEmpty())
{
LoginUser loginUser = getLoginUser();
String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION, true);
if (userService.updateUserAvatar(loginUser.getUserId(), avatar))
{
String oldAvatar = loginUser.getUser().getAvatar();
if (StringUtils.isNotEmpty(oldAvatar))
{
FileUtils.deleteFile(RuoYiConfig.getProfile() + FileUtils.stripPrefix(oldAvatar));
}
AjaxResult ajax = AjaxResult.success();
ajax.put("imgUrl", avatar);
// 更新缓存用户头像
loginUser.getUser().setAvatar(avatar);
tokenService.setLoginUser(loginUser);
return ajax;
}
}
return error("上传图片异常,请联系管理员");
}
/**
* OSS 直传头像 (前端已上传到 OSS, 后端只负责写 sys_user.avatar 字段)
* 入参: { avatarUrl }
*/
@Log(title = "用户头像", businessType = BusinessType.UPDATE)
@PutMapping("/avatarUrl")
public AjaxResult updateAvatarUrl(@RequestBody Map<String, String> body)
{
String avatarUrl = body.get("avatarUrl");
if (StringUtils.isEmpty(avatarUrl))
{
return error("avatarUrl 不能为空");
}
LoginUser loginUser = getLoginUser();
if (userService.updateUserAvatar(loginUser.getUserId(), avatarUrl))
{
// 更新缓存用户头像
loginUser.getUser().setAvatar(avatarUrl);
tokenService.setLoginUser(loginUser);
return success();
}
return error("更新头像失败");
}
}
@@ -0,0 +1,38 @@
package com.ruoyi.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.SysRegisterService;
import com.ruoyi.system.service.ISysConfigService;
/**
* 注册验证
*
* @author ruoyi
*/
@RestController
public class SysRegisterController extends BaseController
{
@Autowired
private SysRegisterService registerService;
@Autowired
private ISysConfigService configService;
@PostMapping("/register")
public AjaxResult register(@RequestBody RegisterBody user)
{
if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
{
return error("当前系统没有开启注册功能!");
}
String msg = registerService.register(user);
return StringUtils.isEmpty(msg) ? success() : error(msg);
}
}
@@ -0,0 +1,254 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
/**
* 角色信息
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/role")
public class SysRoleController extends BaseController
{
@Autowired
private ISysRoleService roleService;
@Autowired
private TokenService tokenService;
@Autowired
private SysPermissionService permissionService;
@Autowired
private ISysUserService userService;
@Autowired
private ISysDeptService deptService;
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/list")
public TableDataInfo list(SysRole role)
{
startPage();
List<SysRole> list = roleService.selectRoleList(role);
return getDataTable(list);
}
@Log(title = "角色管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:role:export')")
@PostMapping("/export")
public void export(HttpServletResponse response, SysRole role)
{
List<SysRole> list = roleService.selectRoleList(role);
ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
util.exportExcel(response, list, "角色数据");
}
/**
* 根据角色编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping(value = "/{roleId}")
public AjaxResult getInfo(@PathVariable Long roleId)
{
roleService.checkRoleDataScope(roleId);
return success(roleService.selectRoleById(roleId));
}
/**
* 新增角色
*/
@PreAuthorize("@ss.hasPermi('system:role:add')")
@Log(title = "角色管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysRole role)
{
if (!roleService.checkRoleNameUnique(role))
{
return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
}
else if (!roleService.checkRoleKeyUnique(role))
{
return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
role.setCreateBy(getUsername());
return toAjax(roleService.insertRole(role));
}
/**
* 修改保存角色
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysRole role)
{
roleService.checkRoleAllowed(role);
roleService.checkRoleDataScope(role.getRoleId());
if (!roleService.checkRoleNameUnique(role))
{
return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
}
else if (!roleService.checkRoleKeyUnique(role))
{
return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
role.setUpdateBy(getUsername());
if (roleService.updateRole(role) > 0)
{
// 刷新所有持有该角色的在线用户权限
tokenService.refreshPermissionByRoleId(role.getRoleId(), permissionService);
return success();
}
return error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
}
/**
* 修改保存数据权限
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.UPDATE)
@PutMapping("/dataScope")
public AjaxResult dataScope(@RequestBody SysRole role)
{
roleService.checkRoleAllowed(role);
roleService.checkRoleDataScope(role.getRoleId());
return toAjax(roleService.authDataScope(role));
}
/**
* 状态修改
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.UPDATE)
@PutMapping("/changeStatus")
public AjaxResult changeStatus(@RequestBody SysRole role)
{
roleService.checkRoleAllowed(role);
roleService.checkRoleDataScope(role.getRoleId());
role.setUpdateBy(getUsername());
return toAjax(roleService.updateRoleStatus(role));
}
/**
* 删除角色
*/
@PreAuthorize("@ss.hasPermi('system:role:remove')")
@Log(title = "角色管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{roleIds}")
public AjaxResult remove(@PathVariable Long[] roleIds)
{
return toAjax(roleService.deleteRoleByIds(roleIds));
}
/**
* 获取角色选择框列表
*/
@PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping("/optionselect")
public AjaxResult optionselect()
{
return success(roleService.selectRoleAll());
}
/**
* 查询已分配用户角色列表
*/
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/authUser/allocatedList")
public TableDataInfo allocatedList(SysUser user)
{
startPage();
List<SysUser> list = userService.selectAllocatedList(user);
return getDataTable(list);
}
/**
* 查询未分配用户角色列表
*/
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/authUser/unallocatedList")
public TableDataInfo unallocatedList(SysUser user)
{
startPage();
List<SysUser> list = userService.selectUnallocatedList(user);
return getDataTable(list);
}
/**
* 取消授权用户
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancel")
public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
{
return toAjax(roleService.deleteAuthUser(userRole));
}
/**
* 批量取消授权用户
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancelAll")
public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
{
return toAjax(roleService.deleteAuthUsers(roleId, userIds));
}
/**
* 批量选择用户授权
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/selectAll")
public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
{
roleService.checkRoleDataScope(roleId);
return toAjax(roleService.insertAuthUsers(roleId, userIds));
}
/**
* 获取对应角色部门树列表
*/
@PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping(value = "/deptTree/{roleId}")
public AjaxResult deptTree(@PathVariable("roleId") Long roleId)
{
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
return ajax;
}
}
@@ -0,0 +1,256 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import java.util.stream.Collectors;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
/**
* 用户信息
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController
{
@Autowired
private ISysUserService userService;
@Autowired
private ISysRoleService roleService;
@Autowired
private ISysDeptService deptService;
@Autowired
private ISysPostService postService;
/**
* 获取用户列表
*/
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/list")
public TableDataInfo list(SysUser user)
{
startPage();
List<SysUser> list = userService.selectUserList(user);
return getDataTable(list);
}
@Log(title = "用户管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:user:export')")
@PostMapping("/export")
public void export(HttpServletResponse response, SysUser user)
{
List<SysUser> list = userService.selectUserList(user);
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
util.exportExcel(response, list, "用户数据");
}
@Log(title = "用户管理", businessType = BusinessType.IMPORT)
@PreAuthorize("@ss.hasPermi('system:user:import')")
@PostMapping("/importData")
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
{
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
List<SysUser> userList = util.importExcel(file.getInputStream());
String operName = getUsername();
String message = userService.importUser(userList, updateSupport, operName);
return success(message);
}
@PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response)
{
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
util.importTemplateExcel(response, "用户数据");
}
/**
* 根据用户编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping(value = { "/", "/{userId}" })
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
{
AjaxResult ajax = AjaxResult.success();
if (StringUtils.isNotNull(userId))
{
userService.checkUserDataScope(userId);
SysUser sysUser = userService.selectUserById(userId);
ajax.put(AjaxResult.DATA_TAG, sysUser);
ajax.put("postIds", postService.selectPostListByUserId(userId));
ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
}
List<SysRole> roles = roleService.selectRoleAll();
ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
ajax.put("posts", postService.selectPostAll());
return ajax;
}
/**
* 新增用户
*/
@PreAuthorize("@ss.hasPermi('system:user:add')")
@Log(title = "用户管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysUser user)
{
deptService.checkDeptDataScope(user.getDeptId());
roleService.checkRoleDataScope(user.getRoleIds());
if (!userService.checkUserNameUnique(user))
{
return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
}
else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
{
return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
}
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
{
return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
user.setCreateBy(getUsername());
user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
return toAjax(userService.insertUser(user));
}
/**
* 修改用户
*/
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysUser user)
{
userService.checkUserAllowed(user);
userService.checkUserDataScope(user.getUserId());
deptService.checkDeptDataScope(user.getDeptId());
roleService.checkRoleDataScope(user.getRoleIds());
if (!userService.checkUserNameUnique(user))
{
return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
}
else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
{
return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
}
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
{
return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
user.setUpdateBy(getUsername());
return toAjax(userService.updateUser(user));
}
/**
* 删除用户
*/
@PreAuthorize("@ss.hasPermi('system:user:remove')")
@Log(title = "用户管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{userIds}")
public AjaxResult remove(@PathVariable Long[] userIds)
{
if (ArrayUtils.contains(userIds, getUserId()))
{
return error("当前用户不能删除");
}
return toAjax(userService.deleteUserByIds(userIds));
}
/**
* 重置密码
*/
@PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping("/resetPwd")
public AjaxResult resetPwd(@RequestBody SysUser user)
{
userService.checkUserAllowed(user);
userService.checkUserDataScope(user.getUserId());
user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
user.setUpdateBy(getUsername());
return toAjax(userService.resetPwd(user));
}
/**
* 状态修改
*/
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping("/changeStatus")
public AjaxResult changeStatus(@RequestBody SysUser user)
{
userService.checkUserAllowed(user);
userService.checkUserDataScope(user.getUserId());
user.setUpdateBy(getUsername());
return toAjax(userService.updateUserStatus(user));
}
/**
* 根据用户编号获取授权角色
*/
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping("/authRole/{userId}")
public AjaxResult authRole(@PathVariable("userId") Long userId)
{
AjaxResult ajax = AjaxResult.success();
SysUser user = userService.selectUserById(userId);
List<SysRole> roles = roleService.selectRolesByUserId(userId);
ajax.put("user", user);
ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
return ajax;
}
/**
* 用户授权角色
*/
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.GRANT)
@PutMapping("/authRole")
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
{
userService.checkUserDataScope(userId);
roleService.checkRoleDataScope(roleIds);
userService.insertUserAuth(userId, roleIds);
return success();
}
/**
* 获取部门树列表
*/
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/deptTree")
public AjaxResult deptTree(SysDept dept)
{
return success(deptService.selectDeptTreeList(dept));
}
}
@@ -0,0 +1,175 @@
package com.ruoyi.web.controller.tool;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* swagger 用户测试方法
*
* @author ruoyi
*/
@Tag(name = "用户信息管理")
@RestController
@RequestMapping("/test/user")
public class TestController extends BaseController
{
private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();
{
users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
}
@Operation(summary = "获取用户列表")
@GetMapping("/list")
public R<List<UserEntity>> userList()
{
List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
return R.ok(userList);
}
@Operation(summary = "获取用户详细")
@GetMapping("/{userId}")
public R<UserEntity> getUser(@PathVariable(name = "userId")
Integer userId)
{
if (!users.isEmpty() && users.containsKey(userId))
{
return R.ok(users.get(userId));
}
else
{
return R.fail("用户不存在");
}
}
@Operation(summary = "新增用户")
@PostMapping("/save")
public R<String> save(UserEntity user)
{
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
{
return R.fail("用户ID不能为空");
}
users.put(user.getUserId(), user);
return R.ok();
}
@Operation(summary = "更新用户")
@PutMapping("/update")
public R<String> update(@RequestBody
UserEntity user)
{
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
{
return R.fail("用户ID不能为空");
}
if (users.isEmpty() || !users.containsKey(user.getUserId()))
{
return R.fail("用户不存在");
}
users.remove(user.getUserId());
users.put(user.getUserId(), user);
return R.ok();
}
@Operation(summary = "删除用户信息")
@DeleteMapping("/{userId}")
public R<String> delete(@PathVariable(name = "userId")
Integer userId)
{
if (!users.isEmpty() && users.containsKey(userId))
{
users.remove(userId);
return R.ok();
}
else
{
return R.fail("用户不存在");
}
}
}
@Schema(description = "用户实体")
class UserEntity
{
@Schema(title = "用户ID")
private Integer userId;
@Schema(title = "用户名称")
private String username;
@Schema(title = "用户密码")
private String password;
@Schema(title = "用户手机")
private String mobile;
public UserEntity()
{
}
public UserEntity(Integer userId, String username, String password, String mobile)
{
this.userId = userId;
this.username = username;
this.password = password;
this.mobile = mobile;
}
public Integer getUserId()
{
return userId;
}
public void setUserId(Integer userId)
{
this.userId = userId;
}
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public String getMobile()
{
return mobile;
}
public void setMobile(String mobile)
{
this.mobile = mobile;
}
}
@@ -0,0 +1,64 @@
package com.ruoyi.web.core.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ruoyi.common.config.RuoYiConfig;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
/**
* Swagger2的接口配置
*
* @author ruoyi
*/
@Configuration
public class SwaggerConfig
{
/** 系统基础配置 */
@Autowired
private RuoYiConfig ruoyiConfig;
/**
* 自定义的 OpenAPI 对象
*/
@Bean
public OpenAPI customOpenApi()
{
return new OpenAPI().components(new Components()
// 设置认证的请求头
.addSecuritySchemes("apikey", securityScheme()))
.addSecurityItem(new SecurityRequirement().addList("apikey"))
.info(getApiInfo());
}
@Bean
public SecurityScheme securityScheme()
{
return new SecurityScheme()
.type(SecurityScheme.Type.APIKEY)
.name("Authorization")
.in(SecurityScheme.In.HEADER)
.scheme("Bearer");
}
/**
* 添加摘要信息
*/
public Info getApiInfo()
{
return new Info()
// 设置标题
.title("标题:若依管理系统_接口文档")
// 描述
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
// 作者信息
.contact(new Contact().name(ruoyiConfig.getName()))
// 版本
.version("版本号:" + ruoyiConfig.getVersion());
}
}
@@ -0,0 +1 @@
restart.include.json=/com.alibaba.fastjson2.*.jar
@@ -0,0 +1,50 @@
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
master:
url: jdbc:mysql://127.0.0.1:3306/guoju0808?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: cu2oh2co3
slave:
enabled: false
url:
username:
password:
initialSize: 5
minIdle: 10
maxActive: 20
maxWait: 60000
connectTimeout: 30000
socketTimeout: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
maxEvictableIdleTimeMillis: 900000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
allow:
url-pattern: /druid/*
login-username: ruoyi
login-password: 123456
filter:
stat:
enabled: true
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
xss:
enabled: true
excludes: /system/notice
urlPatterns: /system/*,/monitor/*,/tool/*
@@ -0,0 +1,167 @@
# 项目相关配置
ruoyi:
# 名称
name: RuoYi
# 版本
version: 3.9.2
# 版权年份
copyrightYear: 2026
# 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath
profile: D:/ruoyi/uploadPath
# 获取ip地址开关
addressEnabled: false
# 验证码类型 math 数字计算 char 字符验证
captchaType: math
# OSS 配置 (前端直传签名, secretKey 仅后端使用)
oss:
enabled: true
endpoint: https://hwtossbamlorgcn.oss-cn-beijing.aliyuncs.com
bucket: hwtossbamlorgcn
accessKeyId: LTAI5tQKWWu96ihmg2VChQsY
accessKeySecret: gA0fTFa8arUYaYA5Us2ClPKVSM1Ypv
dirPrefix: ry8080/
expireSeconds: 3600
# 阿里云短信配置 (hwt-code ali.sms 模式)
# dev/prod 区分走代码: phone 以 "10" 开头视为 dev 测试 (固定码 1234), 其它走 aliyun 真发
sms:
accessKeyId: LTAI5t7S88DmdTxHPzPtJTwG
accessKeySecret: UIkwjMpmlYjgX5IMLjPj8FQNPthdlR
signName: 北京仙仁掌医学科技发展
template: SMS_321560247
inviteTemplate: SMS_492460505
endpoint: dysmsapi.aliyuncs.com
regionId: cn-hangzhou
# 开发环境配置
server:
# 服务器的HTTP端口,默认为8080
port: 8080
servlet:
# 应用的访问路径
context-path: /
tomcat:
# tomcat的URI编码
uri-encoding: UTF-8
# 连接数满后的排队数,默认为100
accept-count: 1000
threads:
# tomcat最大线程数,默认为200
max: 800
# Tomcat启动初始化的线程数,默认值10
min-spare: 100
# 日志配置
logging:
level:
com.ruoyi: debug
org.springframework: debug
com.ruoyi.business: debug
# 用户配置
user:
password:
# 密码最大错误次数
maxRetryCount: 5
# 密码锁定时间(默认10分钟)
lockTime: 10
# Spring配置
spring:
# 资源信息
messages:
# 国际化资源文件路径
basename: i18n/messages
profiles:
active: druid
# 文件上传
servlet:
multipart:
# 单个文件大小
max-file-size: 10MB
# 设置总上传的文件大小
max-request-size: 20MB
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
# 服务模块
devtools:
restart:
# 热部署开关
enabled: true
data:
# redis 配置
redis:
# 地址
host: localhost
# 端口,默认为6379
port: 6379
# 数据库索引
database: 0
# 密码
password:
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# token配置
token:
# 令牌自定义标识
header: Authorization
# 令牌密钥
secret: abcdefghijklmnopqrstuvwxyz
# 令牌有效期(默认30分钟)
expireTime: 30
# MyBatis配置
mybatis:
# 搜索指定包别名
typeAliasesPackage: com.ruoyi.**.domain
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 加载全局的配置文件
configLocation: classpath:mybatis/mybatis-config.xml
# PageHelper分页插件
pagehelper:
helperDialect: mysql
supportMethodsArguments: true
params: count=countSql
# Springdoc配置
springdoc:
api-docs:
path: /v3/api-docs
swagger-ui:
enabled: true
path: /swagger-ui.html
tags-sorter: alpha
group-configs:
- group: 'default'
display-name: '测试模块'
paths-to-match: '/**'
packages-to-scan: com.ruoyi.web.controller.tool
# 防盗链配置
referer:
# 防盗链开关
enabled: false
# 允许的域名列表
allowed-domains: localhost,127.0.0.1,ruoyi.vip,www.ruoyi.vip
# 防止XSS攻击
xss:
# 过滤开关
enabled: true
# 排除链接(多个用逗号分隔)
excludes: /system/notice
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*
@@ -0,0 +1,24 @@
Application Version: ${ruoyi.version}
Spring Boot Version: ${spring-boot.version}
////////////////////////////////////////////////////////////////////
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永不宕机 永无BUG //
////////////////////////////////////////////////////////////////////
@@ -0,0 +1,38 @@
#错误消息
not.null=* 必须填写
user.jcaptcha.error=验证码错误
user.jcaptcha.expire=验证码已失效
user.not.exists=用户不存在/密码错误
user.password.not.match=用户不存在/密码错误
user.password.retry.limit.count=密码输入错误{0}次
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
user.password.delete=对不起,您的账号已被删除
user.blocked=用户已封禁,请联系管理员
role.blocked=角色已封禁,请联系管理员
login.blocked=很遗憾,访问IP已被列入系统黑名单
user.logout.success=退出成功
length.not.valid=长度必须在{min}到{max}个字符之间
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
user.password.not.valid=* 5-50个字符
user.email.not.valid=邮箱格式错误
user.mobile.phone.number.not.valid=手机号格式错误
user.login.success=登录成功
user.register.success=注册成功
user.notfound=请重新登录
user.forcelogout=管理员强制退出,请重新登录
user.unknown.error=未知错误,请重新登录
##文件上传消息
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB!
upload.filename.exceed.length=上传的文件名最长{0}个字符
##权限
no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 日志存放路径 -->
<property name="log.path" value="/home/ruoyi/logs" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 用户访问日志输出 -->
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-user.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
<!--系统用户操作日志-->
<logger name="sys-user" level="info">
<appender-ref ref="sys-user"/>
</logger>
</configuration>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 全局参数 -->
<settings>
<!-- 使全局的映射器启用或禁用缓存 -->
<setting name="cacheEnabled" value="true" />
<!-- 允许JDBC 支持自动生成主键 -->
<setting name="useGeneratedKeys" value="true" />
<!-- 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 -->
<setting name="defaultExecutorType" value="SIMPLE" />
<!-- 指定 MyBatis 所用日志的具体实现 -->
<setting name="logImpl" value="SLF4J" />
<!-- 使用驼峰命名法转换字段 -->
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
</settings>
</configuration>
+40
View File
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.org/POM/4.0.0 http://maven.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.9.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-business</artifactId>
<description>
业务模块 - 北京整合医学学会项目管理系统
</description>
<dependencies>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId>
</dependency>
<!-- 阿里云短信 SMS SDK -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.6.4</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,130 @@
package com.ruoyi.business.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.business.domain.BizOrg;
import com.ruoyi.business.dto.SmsValidForm;
import com.ruoyi.business.service.IBizOrgService;
import com.ruoyi.business.service.SysSmsService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.system.service.ISysUserService;
/**
* 业务登录 - 角色选择
* registerExecutor 完整实现 (2026-08-15 重构, 原 registerSupplier):
* 1. 校验短信验证码
* 2. 检查手机号/用户名是否已注册
* 3. 加密密码
* 4. 插入 sys_user (用户名=前端传入, role_type=executor, 主账号)
* 5. 插入 biz_org (executor 类型, business_nature/contact_phone 从表单)
* 注: 主账号不建 biz_person, 跟 sponsor 主账号保持一致
*/
@RestController
@RequestMapping("/business/auth")
public class BizAuthController extends BaseController {
@Autowired
private SysSmsService smsService;
@Autowired
private ISysUserService userService;
@Autowired
private IBizOrgService bizOrgService;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@PostMapping("/login")
public AjaxResult login(@RequestBody Map<String, Object> body) {
String username = (String) body.get("username");
String password = (String) body.get("password");
String roleType = (String) body.get("roleType");
return success().put("roleType", roleType).put("token", "mock-token");
}
@PostMapping("/registerExecutor")
public AjaxResult registerExecutor(@RequestBody Map<String, Object> body) {
String username = (String) body.get("username");
String unitName = (String) body.get("unitName");
String businessNature = (String) body.get("businessNature");
String phone = (String) body.get("phone");
String code = (String) body.get("smsCode");
String password = (String) body.get("password");
String confirmPassword = (String) body.get("confirmPassword");
String uuid = (String) body.get("uuid");
// 1. 基础校验
if (username == null || username.length() < 4 || username.length() > 20) return error("用户名长度 4-20 位");
if (!username.matches("^[A-Za-z0-9_]+$")) return error("用户名只能包含字母/数字/下划线");
if (unitName == null || unitName.isEmpty()) return error("企业名称不能为空");
if (businessNature == null || businessNature.isEmpty()) return error("企业性质不能为空");
if (phone == null || !phone.matches("^1\\d{10}$")) return error("手机号格式错误");
if (code == null || code.isEmpty()) return error("请输入短信验证码");
if (password == null || password.length() < 6 || password.length() > 20) return error("密码长度 6-20 位");
if (!password.equals(confirmPassword)) return error("两次密码输入不一致");
// 2. 校验短信验证码
SmsValidForm smsForm = new SmsValidForm();
smsForm.setPhone(phone);
smsForm.setSmsCode(code);
smsForm.setUuid(uuid);
try {
smsService.verifyCode(smsForm);
} catch (RuntimeException e) {
return error("验证码错误或已过期: " + e.getMessage());
}
// 3. 检查手机号/用户名是否已注册
if (userService.isPhoneRegistered(phone)) {
return error("该手机号已注册, 请直接登录");
}
SysUser nameCheck = new SysUser();
nameCheck.setUserName(username);
if (!userService.checkUserNameUnique(nameCheck)) {
return error("用户名已被占用: " + username);
}
// 4. 加密密码 + 插入 sys_user (用户名=userName 字段, 主账号)
SysUser user = new SysUser();
user.setUserName(username);
user.setNickName(unitName); // 默认昵称用公司名, 用户后续可在账号页改
user.setPhonenumber(phone);
user.setPassword(passwordEncoder.encode(password));
user.setStatus("0");
userService.insertUser(user);
Long userId = user.getUserId();
// sys_user.role_type 字段需 = executor
userService.updateRoleType(userId, "executor");
// 5. 插入 biz_org (executor 类型, 主账号自己当 contact)
BizOrg org = new BizOrg();
org.setOrgId(null);
org.setOrgName(unitName);
org.setOrgType("executor");
org.setBusinessNature(businessNature);
org.setContactPhone(phone);
org.setContactName(unitName); // 联系人默认 = 公司名
org.setStatus("0");
bizOrgService.insert(org);
Long orgId = org.getOrgId();
// 注: 主账号不建 biz_person (与 sponsor 主账号保持一致, 见 sponsor/Account.vue)
// 后续主账号在 [账号信息] 看到 [所属公司] 时, 后端可通过 sys_user.role_type 关联 biz_org 取 org_name
// 子账号 (biz_person.unit_type='sponsor' + user_id 关联 sys_user.parent_user_id) 由 [人员管理] 创建
return success("注册成功, 请等待审核").put("userId", userId).put("orgId", orgId);
}
@PostMapping("/registerSponsor")
public AjaxResult registerSponsor(@RequestBody Map<String, Object> body) {
return success();
}
}
@@ -0,0 +1,56 @@
package com.ruoyi.business.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.business.domain.BizProject;
import com.ruoyi.business.domain.BizMeeting;
import com.ruoyi.business.domain.BizExpert;
import com.ruoyi.business.service.IBizProjectService;
import com.ruoyi.business.service.IBizMeetingService;
import com.ruoyi.business.service.IBizExpertService;
/**
* 工作台统计
*/
@RestController
@RequestMapping("/business/dashboard")
public class BizDashboardController extends BaseController {
@Autowired private IBizProjectService bizProjectService;
@Autowired private IBizMeetingService bizMeetingService;
@Autowired private IBizExpertService bizExpertService;
@GetMapping("/manager")
public AjaxResult managerDashboard() {
Map<String, Object> map = new HashMap<>();
List<BizProject> projects = bizProjectService.selectList(new BizProject());
List<BizMeeting> meetings = bizMeetingService.selectList(new BizMeeting());
List<BizExpert> experts = bizExpertService.selectList(new BizExpert());
map.put("totalProjects", projects.size());
map.put("totalMeetings", meetings.size());
map.put("totalExperts", experts.size());
map.put("todoMeetings", meetings.stream().filter(m -> "未执行".equals(m.getCurrentStage())).count());
map.put("doingMeetings", meetings.stream().filter(m -> "待监管".equals(m.getCurrentStage()) || "待整改".equals(m.getCurrentStage())).count());
map.put("doneMeetings", meetings.stream().filter(m -> "已结算".equals(m.getCurrentStage()) || "已结题".equals(m.getCurrentStage())).count());
return success(map);
}
@GetMapping("/leader")
public AjaxResult leaderDashboard() {
Map<String, Object> map = new HashMap<>();
List<BizProject> projects = bizProjectService.selectList(new BizProject());
List<BizMeeting> meetings = bizMeetingService.selectList(new BizMeeting());
map.put("totalProjects", projects.size());
map.put("totalMeetings", meetings.size());
map.put("finishedProjects", projects.stream().filter(p -> "1".equals(p.getIsFinished())).count());
map.put("finishedMeetings", meetings.stream().filter(m -> "已结题".equals(m.getCurrentStage())).count());
return success(map);
}
}
@@ -0,0 +1,142 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.business.domain.BizDepartment;
import com.ruoyi.business.domain.BizDoctorTitle;
import com.ruoyi.business.service.IBizDepartmentService;
import com.ruoyi.business.service.IBizDoctorTitleService;
/**
* 业务字典管理 (科室 + 医生职称)
* 仅管理员可维护; 其它角色可访问 /active 接口拉启用的列表
*/
@RestController
@RequestMapping("/business/dict")
public class BizDictController extends BaseController
{
@Autowired
private IBizDepartmentService departmentService;
@Autowired
private IBizDoctorTitleService doctorTitleService;
// ============== 科室 ==============
@PreAuthorize("@ss.hasRole('admin')")
@GetMapping("/department/list")
public TableDataInfo listDept(BizDepartment entity)
{
startPage();
return getDataTable(departmentService.selectList(entity));
}
@GetMapping("/department/active")
public AjaxResult activeDept()
{
return success(departmentService.selectActive());
}
@GetMapping("/department/{deptId}")
public AjaxResult getDept(@PathVariable Long deptId)
{
return success(departmentService.getById(deptId));
}
@PreAuthorize("@ss.hasRole('admin')")
@Log(title = "科室字典", businessType = BusinessType.INSERT)
@PostMapping("/department")
public AjaxResult addDept(@RequestBody BizDepartment entity)
{
if (entity.getName() == null || entity.getName().trim().isEmpty()) {
return error("科室名称不能为空");
}
if (entity.getStatus() == null || entity.getStatus().isEmpty()) entity.setStatus("0");
entity.setCreateBy(SecurityUtils.getUsername());
return toAjax(departmentService.insert(entity));
}
@PreAuthorize("@ss.hasRole('admin')")
@Log(title = "科室字典", businessType = BusinessType.UPDATE)
@PutMapping("/department")
public AjaxResult editDept(@RequestBody BizDepartment entity)
{
if (entity.getDeptId() == null) return error("ID 不能为空");
if (entity.getName() == null || entity.getName().trim().isEmpty()) {
return error("科室名称不能为空");
}
entity.setUpdateBy(SecurityUtils.getUsername());
return toAjax(departmentService.updateByPrimaryKey(entity));
}
@PreAuthorize("@ss.hasRole('admin')")
@Log(title = "科室字典", businessType = BusinessType.DELETE)
@DeleteMapping("/department/{ids}")
public AjaxResult removeDept(@PathVariable Long[] ids)
{
return toAjax(departmentService.deleteByPrimaryKeys(ids));
}
// ============== 医生职称 ==============
@PreAuthorize("@ss.hasRole('admin')")
@GetMapping("/title/list")
public TableDataInfo listTitle(BizDoctorTitle entity)
{
startPage();
return getDataTable(doctorTitleService.selectList(entity));
}
@GetMapping("/title/active")
public AjaxResult activeTitle()
{
return success(doctorTitleService.selectActive());
}
@GetMapping("/title/{titleId}")
public AjaxResult getTitle(@PathVariable Long titleId)
{
return success(doctorTitleService.getById(titleId));
}
@PreAuthorize("@ss.hasRole('admin')")
@Log(title = "医生职称字典", businessType = BusinessType.INSERT)
@PostMapping("/title")
public AjaxResult addTitle(@RequestBody BizDoctorTitle entity)
{
if (entity.getName() == null || entity.getName().trim().isEmpty()) {
return error("职称名称不能为空");
}
if (entity.getStatus() == null || entity.getStatus().isEmpty()) entity.setStatus("0");
entity.setCreateBy(SecurityUtils.getUsername());
return toAjax(doctorTitleService.insert(entity));
}
@PreAuthorize("@ss.hasRole('admin')")
@Log(title = "医生职称字典", businessType = BusinessType.UPDATE)
@PutMapping("/title")
public AjaxResult editTitle(@RequestBody BizDoctorTitle entity)
{
if (entity.getTitleId() == null) return error("ID 不能为空");
if (entity.getName() == null || entity.getName().trim().isEmpty()) {
return error("职称名称不能为空");
}
entity.setUpdateBy(SecurityUtils.getUsername());
return toAjax(doctorTitleService.updateByPrimaryKey(entity));
}
@PreAuthorize("@ss.hasRole('admin')")
@Log(title = "医生职称字典", businessType = BusinessType.DELETE)
@DeleteMapping("/title/{ids}")
public AjaxResult removeTitle(@PathVariable Long[] ids)
{
return toAjax(doctorTitleService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,122 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.business.domain.BizExecutionIntent;
import com.ruoyi.business.domain.BizProject;
import com.ruoyi.business.service.IBizExecutionIntentService;
import com.ruoyi.business.service.IBizProjectService;
/**
* 执行意向Controller
*/
@RestController
@RequestMapping("/business/executionIntent")
public class BizExecutionIntentController extends BaseController
{
@Autowired
private SysUserMapper sysUserMapper;
@Autowired
private IBizExecutionIntentService bizExecutionIntentService;
@Autowired
private IBizProjectService bizProjectService;
/**
* 公开门户点击"立即报名" — 写入意向 (user_id = 当前登录用户)
* POST /business/executionIntent/signup
* body: { projectId } (后端按 id 查项目回填 no/name)
* 返回 { intentId, projectNo, projectName, onboardStatus }
*/
@Log(title = "执行意向", businessType = BusinessType.INSERT)
@PostMapping("/signup")
public AjaxResult signup(@RequestBody BizExecutionIntent bizExecutionIntent)
{
// 入参只接受 projectId (项目主键)
// BizExecutionIntent 没有 projectId 字段, 用 params 暂存
Object pidRaw = bizExecutionIntent.getParams().get("projectId");
Long projectId = null;
if (pidRaw != null) {
try { projectId = Long.parseLong(String.valueOf(pidRaw)); } catch (Exception e) { return error("项目ID格式错误"); }
}
if (projectId == null) return error("项目ID不能为空");
BizProject proj = bizProjectService.getById(String.valueOf(projectId));
if (proj == null) return error("项目不存在");
// 查重: 当前用户是否已报过这个项目
BizExecutionIntent q = new BizExecutionIntent();
q.setUserId(SecurityUtils.getUserId());
q.setProjectNo(proj.getProjectNo());
List<BizExecutionIntent> exists = bizExecutionIntentService.selectList(q);
if (exists != null && !exists.isEmpty()) return error("您已报名过该项目,无需重复报名");
bizExecutionIntent.setProjectNo(proj.getProjectNo());
bizExecutionIntent.setProjectName(proj.getProjectName());
Long uid = SecurityUtils.getUserId();
bizExecutionIntent.setUserId(uid);
// 默认按用户表信息补全 name/phone (意向表历史字段, 方便后续审核流使用)
SysUser u = sysUserMapper.selectUserById(uid);
if (u != null) {
if (bizExecutionIntent.getName() == null || bizExecutionIntent.getName().isEmpty())
bizExecutionIntent.setName(u.getUserName());
if (bizExecutionIntent.getPhone() == null || bizExecutionIntent.getPhone().isEmpty())
bizExecutionIntent.setPhone(u.getPhonenumber());
}
if (bizExecutionIntent.getOnboardStatus() == null) bizExecutionIntent.setOnboardStatus("未入库");
bizExecutionIntent.setCreateBy(SecurityUtils.getUsername());
int n = bizExecutionIntentService.insert(bizExecutionIntent);
if (n == 0) return error("报名失败");
return success(bizExecutionIntent);
}
/** 当前用户是否已报过该项目 */
@GetMapping("/hasSigned")
public AjaxResult hasSigned(@RequestParam("projectId") Long projectId)
{
if (projectId == null) return success(false);
BizProject proj = bizProjectService.getById(String.valueOf(projectId));
if (proj == null) return success(false);
BizExecutionIntent q = new BizExecutionIntent();
q.setUserId(SecurityUtils.getUserId());
q.setProjectNo(proj.getProjectNo());
List<BizExecutionIntent> exists = bizExecutionIntentService.selectList(q);
return success(exists != null && !exists.isEmpty());
}
@GetMapping("/list")
public TableDataInfo list(BizExecutionIntent bizExecutionIntent)
{
startPage();
List<BizExecutionIntent> list = bizExecutionIntentService.selectList(bizExecutionIntent);
return getDataTable(list);
}
@GetMapping("/{intentId}")
public AjaxResult getInfo(@PathVariable("intentId") String intentId)
{
return success(bizExecutionIntentService.getById(intentId));
}
@Log(title = "执行意向", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizExecutionIntent bizExecutionIntent)
{
return toAjax(bizExecutionIntentService.insert(bizExecutionIntent));
}
@Log(title = "执行意向", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizExecutionIntent bizExecutionIntent)
{
return toAjax(bizExecutionIntentService.updateByPrimaryKey(bizExecutionIntent));
}
@Log(title = "执行意向", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizExecutionIntentService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,74 @@
package com.ruoyi.business.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
/**
* 执行方用户查询 Controller
* 绕开 RuoYi 的 sys_user:list 权限(manager01 等普通用户被 data_scope 过滤看不到)。
* 按 sys_user.role_type = 'executor' 过滤真正的执行方用户。
*/
@RestController
@RequestMapping("/business/executor")
public class BizExecutorController extends BaseController
{
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* 查询指定角色用户列表 (支持 executor / sponsor / manager / leader / doctor / admin)
* @param roleType 角色类型 (默认 'executor')
* @param userName 用户名模糊搜索 (可选)
* @param userId 精确匹配 (可选)
* @param pageSize 限制返回行数 (默认 50)
*/
@GetMapping("/list")
public AjaxResult list(@RequestParam(required = false, defaultValue = "executor") String roleType,
@RequestParam(required = false) String userName,
@RequestParam(required = false) Long userId,
@RequestParam(required = false, defaultValue = "50") Integer pageSize)
{
StringBuilder sql = new StringBuilder()
.append("SELECT user_id, dept_id, user_name, nick_name, email, phonenumber, role_type, status, create_time ")
.append("FROM sys_user WHERE del_flag = '0' AND status = '0' AND role_type = ?");
List<Object> args = new ArrayList<>();
args.add(roleType);
if (userId != null) {
sql.append(" AND user_id = ?");
args.add(userId);
}
if (userName != null && !userName.isEmpty()) {
sql.append(" AND user_name LIKE ?");
args.add("%" + userName + "%");
}
sql.append(" ORDER BY user_id ASC LIMIT ?");
args.add(pageSize);
List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql.toString(), args.toArray());
// 标准化为前端 el-select 友好的字段
List<Map<String, Object>> result = new ArrayList<>();
for (Map<String, Object> r : rows) {
Map<String, Object> u = new HashMap<>();
u.put("userId", r.get("user_id"));
u.put("deptId", r.get("dept_id"));
u.put("userName", r.get("user_name"));
u.put("nickName", r.get("nick_name"));
u.put("email", r.get("email"));
u.put("phonenumber", r.get("phonenumber"));
u.put("roleType", r.get("role_type"));
u.put("status", r.get("status"));
result.add(u);
}
return success(result);
}
}
@@ -0,0 +1,74 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.business.domain.BizExpert;
import com.ruoyi.business.service.IBizExpertService;
/**
* 专家Controller
*/
@RestController
@RequestMapping("/business/expert")
public class BizExpertController extends BaseController
{
@Autowired
private IBizExpertService bizExpertService;
@GetMapping("/list")
public TableDataInfo list(BizExpert bizExpert)
{
startPage();
List<BizExpert> list = bizExpertService.selectList(bizExpert);
return getDataTable(list);
}
@GetMapping("/{expertId}")
public AjaxResult getInfo(@PathVariable("expertId") String expertId)
{
return success(bizExpertService.getById(expertId));
}
/**
* 查当前登录用户的专家信息 (按 userId 路由)
*/
@GetMapping("/profile")
public AjaxResult getProfile()
{
return success(bizExpertService.getByUserId(SecurityUtils.getUserId()));
}
@Log(title = "专家", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizExpert bizExpert)
{
return toAjax(bizExpertService.insert(bizExpert));
}
@Log(title = "专家", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizExpert bizExpert)
{
return toAjax(bizExpertService.updateByPrimaryKey(bizExpert));
}
/**
* 个人专家信息更新 (走 userId 路由, 后端强制注入当前登录用户)
* 不依赖前端传 expertId; 找不到 expert 行时自动 insert
*/
@Log(title = "专家个人信息", businessType = BusinessType.UPDATE)
@PutMapping("/profile")
public AjaxResult updateProfile(@RequestBody BizExpert bizExpert)
{
bizExpert.setUserId(SecurityUtils.getUserId());
bizExpert.setCreateBy(SecurityUtils.getUsername());
return toAjax(bizExpertService.updateProfileByUserId(bizExpert));
}
@Log(title = "专家", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizExpertService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,53 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.BizInvitation;
import com.ruoyi.business.service.IBizInvitationService;
/**
* 邀请函Controller
*/
@RestController
@RequestMapping("/business/invitation")
public class BizInvitationController extends BaseController
{
@Autowired
private IBizInvitationService bizInvitationService;
@GetMapping("/list")
public TableDataInfo list(BizInvitation bizInvitation)
{
startPage();
List<BizInvitation> list = bizInvitationService.selectList(bizInvitation);
return getDataTable(list);
}
@GetMapping("/{invitationId}")
public AjaxResult getInfo(@PathVariable("invitationId") String invitationId)
{
return success(bizInvitationService.getById(invitationId));
}
@Log(title = "邀请函", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizInvitation bizInvitation)
{
return toAjax(bizInvitationService.insert(bizInvitation));
}
@Log(title = "邀请函", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizInvitation bizInvitation)
{
return toAjax(bizInvitationService.updateByPrimaryKey(bizInvitation));
}
@Log(title = "邀请函", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizInvitationService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,53 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.BizLaborVoucher;
import com.ruoyi.business.service.IBizLaborVoucherService;
/**
* 劳务凭证Controller
*/
@RestController
@RequestMapping("/business/laborVoucher")
public class BizLaborVoucherController extends BaseController
{
@Autowired
private IBizLaborVoucherService bizLaborVoucherService;
@GetMapping("/list")
public TableDataInfo list(BizLaborVoucher bizLaborVoucher)
{
startPage();
List<BizLaborVoucher> list = bizLaborVoucherService.selectList(bizLaborVoucher);
return getDataTable(list);
}
@GetMapping("/{voucherId}")
public AjaxResult getInfo(@PathVariable("voucherId") String voucherId)
{
return success(bizLaborVoucherService.getById(voucherId));
}
@Log(title = "劳务凭证", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizLaborVoucher bizLaborVoucher)
{
return toAjax(bizLaborVoucherService.insert(bizLaborVoucher));
}
@Log(title = "劳务凭证", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizLaborVoucher bizLaborVoucher)
{
return toAjax(bizLaborVoucherService.updateByPrimaryKey(bizLaborVoucher));
}
@Log(title = "劳务凭证", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizLaborVoucherService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,53 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.BizMeeting;
import com.ruoyi.business.service.IBizMeetingService;
/**
* 会议Controller
*/
@RestController
@RequestMapping("/business/meeting")
public class BizMeetingController extends BaseController
{
@Autowired
private IBizMeetingService bizMeetingService;
@GetMapping("/list")
public TableDataInfo list(BizMeeting bizMeeting)
{
startPage();
List<BizMeeting> list = bizMeetingService.selectList(bizMeeting);
return getDataTable(list);
}
@GetMapping("/{meetingId}")
public AjaxResult getInfo(@PathVariable("meetingId") String meetingId)
{
return success(bizMeetingService.getById(meetingId));
}
@Log(title = "会议", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizMeeting bizMeeting)
{
return toAjax(bizMeetingService.insert(bizMeeting));
}
@Log(title = "会议", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizMeeting bizMeeting)
{
return toAjax(bizMeetingService.updateByPrimaryKey(bizMeeting));
}
@Log(title = "会议", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizMeetingService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,53 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.BizMeetingSettlement;
import com.ruoyi.business.service.IBizMeetingSettlementService;
/**
* 会议结算Controller
*/
@RestController
@RequestMapping("/business/meetingSettlement")
public class BizMeetingSettlementController extends BaseController
{
@Autowired
private IBizMeetingSettlementService bizMeetingSettlementService;
@GetMapping("/list")
public TableDataInfo list(BizMeetingSettlement bizMeetingSettlement)
{
startPage();
List<BizMeetingSettlement> list = bizMeetingSettlementService.selectList(bizMeetingSettlement);
return getDataTable(list);
}
@GetMapping("/{settlementId}")
public AjaxResult getInfo(@PathVariable("settlementId") String settlementId)
{
return success(bizMeetingSettlementService.getById(settlementId));
}
@Log(title = "会议结算", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizMeetingSettlement bizMeetingSettlement)
{
return toAjax(bizMeetingSettlementService.insert(bizMeetingSettlement));
}
@Log(title = "会议结算", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizMeetingSettlement bizMeetingSettlement)
{
return toAjax(bizMeetingSettlementService.updateByPrimaryKey(bizMeetingSettlement));
}
@Log(title = "会议结算", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizMeetingSettlementService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,128 @@
package com.ruoyi.business.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.business.domain.BizMessage;
import com.ruoyi.business.service.IBizMessageService;
/**
* 个人消息Controller
*/
@RestController
@RequestMapping("/business/message")
public class BizMessageController extends BaseController
{
@Autowired
private IBizMessageService bizMessageService;
/**
* 列表 (管理员视角: 全量 + 过滤)
*/
@PreAuthorize("@ss.hasPermi('business:message:list')")
@GetMapping("/list")
public TableDataInfo list(BizMessage bizMessage)
{
startPage();
List<BizMessage> list = bizMessageService.selectList(bizMessage);
return getDataTable(list);
}
/**
* 当前登录用户的最近消息 (含未读统计)
* GET /business/message/my?limit=50
* 返回 {rows: [...], unread: 12}
*/
@GetMapping("/my")
public AjaxResult my(@RequestParam(value = "limit", required = false, defaultValue = "50") Integer limit)
{
Long uid = SecurityUtils.getUserId();
List<BizMessage> rows = bizMessageService.selectMyRecent(uid, limit);
int unread = 0;
for (BizMessage m : rows) {
if ("0".equals(m.getIsRead())) unread++;
}
Map<String, Object> data = new HashMap<>();
data.put("rows", rows);
data.put("unread", unread);
data.put("total", rows.size());
return success(data);
}
/**
* 标记单条已读 (校验归属)
*/
@PutMapping("/read/{msgId}")
public AjaxResult markRead(@PathVariable Long msgId)
{
Long uid = SecurityUtils.getUserId();
int n = bizMessageService.markRead(msgId, uid);
return n > 0 ? success() : error("消息不存在或无权操作");
}
/**
* 当前用户全部标记已读
*/
@PutMapping("/readAll")
public AjaxResult markAllRead()
{
Long uid = SecurityUtils.getUserId();
int n = bizMessageService.markAllRead(uid);
return success(n);
}
/**
* 详情 (校验归属)
*/
@GetMapping("/{msgId}")
public AjaxResult getInfo(@PathVariable Long msgId)
{
BizMessage m = bizMessageService.getById(msgId);
if (m == null) return error("消息不存在");
// 非管理员只能看自己的
if (!SecurityUtils.isAdmin() && !m.getReceiverUserId().equals(SecurityUtils.getUserId())) {
return error("无权查看");
}
// 自动标记已读
if ("0".equals(m.getIsRead()) && m.getReceiverUserId().equals(SecurityUtils.getUserId())) {
bizMessageService.markRead(msgId, SecurityUtils.getUserId());
m.setIsRead("1");
}
return success(m);
}
/**
* 发送消息给某用户 (管理员)
*/
@PreAuthorize("@ss.hasPermi('business:message:add')")
@Log(title = "个人消息", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizMessage bizMessage)
{
if (bizMessage.getReceiverUserId() == null) return error("接收人不能为空");
if (bizMessage.getTitle() == null || bizMessage.getTitle().isEmpty()) return error("标题不能为空");
bizMessage.setCreateBy(SecurityUtils.getUsername());
return toAjax(bizMessageService.insert(bizMessage));
}
/**
* 批量删除 (管理员)
*/
@PreAuthorize("@ss.hasPermi('business:message:remove')")
@Log(title = "个人消息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(bizMessageService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,53 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.BizOrg;
import com.ruoyi.business.service.IBizOrgService;
/**
* 公司Controller (赞助方 + 执行方 共用)
* GET /business/org/list?orgType=sponsor|execution
*/
@RestController
@RequestMapping("/business/org")
public class BizOrgController extends BaseController {
@Autowired
private IBizOrgService bizOrgService;
@GetMapping("/list")
public TableDataInfo list(BizOrg bizOrg) {
startPage();
List<BizOrg> list = bizOrgService.selectList(bizOrg);
return getDataTable(list);
}
@GetMapping("/{orgId}")
public AjaxResult getInfo(@PathVariable("orgId") Long orgId) {
return success(bizOrgService.getById(orgId));
}
@Log(title = "公司管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizOrg bizOrg) {
return toAjax(bizOrgService.insert(bizOrg));
}
@Log(title = "公司管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizOrg bizOrg) {
return toAjax(bizOrgService.updateByPrimaryKey(bizOrg));
}
@Log(title = "公司管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{orgIds}")
public AjaxResult remove(@PathVariable Long[] orgIds) {
return toAjax(bizOrgService.deleteByPrimaryKeys(orgIds));
}
}
@@ -0,0 +1,172 @@
package com.ruoyi.business.controller;
import java.util.ArrayList;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.business.domain.BizOrg;
import com.ruoyi.business.domain.BizPerson;
import com.ruoyi.business.domain.BizPersonImportVO;
import com.ruoyi.business.mapper.BizOrgMapper;
import com.ruoyi.business.service.IBizPersonService;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
/**
* 人员Controller
*/
@RestController
@RequestMapping("/business/person")
public class BizPersonController extends BaseController
{
@Autowired
private IBizPersonService bizPersonService;
@Autowired
private BizOrgMapper bizOrgMapper;
@GetMapping("/list")
public TableDataInfo list(BizPerson bizPerson)
{
startPage();
List<BizPerson> list = bizPersonService.selectList(bizPerson);
return getDataTable(list);
}
/**
* sponsor 端专属人员列表 (走专属 mapper, 利用 biz_person.user_id -> sys_user.parent_user_id 做归属过滤)
* 公共 /list 方法不被 sponsor 专属逻辑污染
*/
@GetMapping("/sponsorList")
public TableDataInfo sponsorList(BizPerson bizPerson)
{
Long mainUid = getUserId();
bizPerson.getParams().put("sponsorOwnerUid", mainUid);
startPage();
List<BizPerson> list = bizPersonService.selectSponsorList(bizPerson);
return getDataTable(list);
}
@GetMapping("/{personId}")
public AjaxResult getInfo(@PathVariable("personId") String personId)
{
return success(bizPersonService.getById(personId));
}
@Log(title = "人员", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizPerson bizPerson)
{
bizPerson.setCreateBy(getUsername());
bizPerson.setUpdateBy(getUsername());
// sponsor 端新建人员 = 创建 sys_user 子账号 (SUB, parent=当前登录主账号)
// service 内: 创建 sys_user + 创建 biz_person + 把 sys_user.user_id 绑到 biz_person.user_id
SysUser created = bizPersonService.insert(bizPerson, getUserId());
AjaxResult ajax = success(created);
// SysUser.password 是 @JsonProperty WRITE_ONLY 不会序列化,这里额外 put 明文密码给前端 toast
ajax.put("password", bizPerson.getLoginPassword());
return ajax;
}
@Log(title = "人员", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizPerson bizPerson)
{
bizPerson.setUpdateBy(getUsername());
return toAjax(bizPersonService.updateByPrimaryKey(bizPerson));
}
@Log(title = "人员", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizPersonService.deleteByPrimaryKeys(ids));
}
// ========== sponsor 端 Excel 批量导入 ==========
/**
* 下载 sponsor 端人员导入模板 (.xlsx)
* 模板列头按 BizPersonImportVO @Excel 注解自动生成 (中文: 姓名/手机号/工作单位/部门/职务/角色/状态)
*/
@GetMapping("/sponsorImportTemplate")
public void sponsorImportTemplate(HttpServletResponse response)
{
ExcelUtil<BizPersonImportVO> util = new ExcelUtil<>(BizPersonImportVO.class);
util.importTemplateExcel(response, "人员导入");
}
/**
* sponsor 端批量导入人员 (上传 .xlsx)
* 每行创建一个 biz_person + 一个 sys_user 子账号 (parent_user_id=当前主账号, loginUsername=手机号, 默认密码 123456)
* 失败行记录在返回结果的 errorRows 字段, 不影响其他行
*/
@Log(title = "人员批量导入", businessType = BusinessType.INSERT)
@PostMapping("/sponsorImport")
public AjaxResult sponsorImport(@RequestParam("file") MultipartFile file) throws Exception
{
if (file == null || file.isEmpty()) {
throw new ServiceException("请选择要上传的文件");
}
ExcelUtil<BizPersonImportVO> util = new ExcelUtil<>(BizPersonImportVO.class);
List<BizPersonImportVO> rows = util.importExcel(file.getInputStream(), 0);
if (rows == null || rows.isEmpty()) {
throw new ServiceException("导入文件无有效数据");
}
Long mainUid = getUserId();
List<java.util.Map<String, Object>> results = new ArrayList<>();
int ok = 0;
for (int i = 0; i < rows.size(); i++) {
BizPersonImportVO row = rows.get(i);
java.util.Map<String, Object> r = new java.util.LinkedHashMap<>();
r.put("rowNo", i + 2); // Excel 行号 (含标题行)
r.put("name", row.getName());
r.put("phone", row.getPhone());
try {
// 1. orgName → orgId (按 orgType='sponsor' 精确匹配, 查不到就报错)
String orgName = row.getOrgName();
if (orgName == null || orgName.trim().isEmpty()) {
throw new ServiceException("所属公司不能为空");
}
BizOrg orgQuery = new BizOrg();
orgQuery.setOrgName(orgName.trim());
orgQuery.setOrgType("sponsor");
List<BizOrg> matched = bizOrgMapper.selectList(orgQuery);
if (matched == null || matched.isEmpty()) {
throw new ServiceException("找不到所属公司: " + orgName + " (需先在 [公司管理] 录入 orgType=sponsor 的公司)");
}
Long orgId = matched.get(0).getOrgId();
BizPerson p = new BizPerson();
p.setName(row.getName());
p.setPhone(row.getPhone());
p.setOrgId(orgId);
p.setDepartment(row.getDepartment());
p.setPosition(row.getPosition());
p.setRole(row.getRole());
p.setStatus("0"); // 默认正常
p.setUnitType("sponsor");
p.setLoginUsername(row.getPhone()); // 用户名 = 手机号 (要求唯一)
p.setLoginPassword("123456"); // 默认密码
p.setCreateBy(getUsername());
p.setUpdateBy(getUsername());
bizPersonService.insert(p, mainUid);
ok++;
r.put("ok", true);
r.put("message", "成功");
} catch (Exception e) {
r.put("ok", false);
r.put("message", e.getMessage());
}
results.add(r);
}
AjaxResult ajax = success();
ajax.put("total", rows.size());
ajax.put("ok", ok);
ajax.put("results", results);
return ajax;
}
}
@@ -0,0 +1,214 @@
package com.ruoyi.business.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.business.domain.BizExecutionIntent;
import com.ruoyi.business.domain.BizProject;
import com.ruoyi.business.domain.BizProjectAssign;
import com.ruoyi.business.domain.BizProjectRating;
import com.ruoyi.business.service.IBizProjectService;
import com.ruoyi.business.service.IBizExecutionIntentService;
import com.ruoyi.business.domain.BizProjectSponsorAssign;
import com.ruoyi.business.service.IBizProjectAssignService;
import com.ruoyi.business.service.IBizProjectRatingService;
import com.ruoyi.business.service.IBizProjectSponsorAssignService;
/**
* 项目Controller
*
* 评分说明: 评分公开 (无可见性), 由 rater_role 字段区分角色 (sponsor/executor/compliance)
* 一律走 biz_project_rating 中间表 (BizProjectRatingController 已提供完整 CRUD)
*/
@RestController
@RequestMapping("/business/project")
public class BizProjectController extends BaseController
{
@Autowired
private IBizProjectService bizProjectService;
@Autowired
private IBizExecutionIntentService bizExecutionIntentService;
@Autowired
private IBizProjectAssignService bizProjectAssignService;
@Autowired
private IBizProjectRatingService bizProjectRatingService;
@Autowired
private IBizProjectSponsorAssignService bizProjectSponsorAssignService;
/**
* 我报名的项目 (当前用户在 biz_execution_intent 里有意向的项目)
* GET /business/project/myProjects
*/
@GetMapping("/myProjects")
public TableDataInfo myProjects(BizProject bizProject)
{
Long uid = SecurityUtils.getUserId();
BizExecutionIntent q = new BizExecutionIntent();
q.setUserId(uid);
List<BizExecutionIntent> intents = bizExecutionIntentService.selectList(q);
if (intents == null || intents.isEmpty()) {
TableDataInfo r = new TableDataInfo();
r.setRows(new ArrayList<>());
r.setTotal(0);
return r;
}
java.util.Set<String> noSet = new java.util.LinkedHashSet<>();
for (BizExecutionIntent it : intents) {
if (it.getProjectNo() != null && !it.getProjectNo().isEmpty()) noSet.add(it.getProjectNo());
}
startPage();
BizProject bp = new BizProject();
bp.getParams().put("projectNos", new ArrayList<>(noSet));
if (bizProject.getProjectNo() != null) bp.setProjectNo(bizProject.getProjectNo());
if (bizProject.getProjectName() != null) bp.setProjectName(bizProject.getProjectName());
List<BizProject> list = bizProjectService.selectList(bp);
return getDataTable(list);
}
@GetMapping("/list")
public TableDataInfo list(BizProject bizProject)
{
startPage();
List<BizProject> list = bizProjectService.selectList(bizProject);
return getDataTable(list);
}
@GetMapping("/{projectId}")
public AjaxResult getInfo(@PathVariable("projectId") String projectId)
{
return success(bizProjectService.getById(projectId));
}
@Log(title = "项目", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizProject bizProject)
{
return toAjax(bizProjectService.insert(bizProject));
}
@Log(title = "项目", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizProject bizProject)
{
return toAjax(bizProjectService.updateByPrimaryKey(bizProject));
}
@Log(title = "项目", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizProjectService.deleteByPrimaryKeys(ids));
}
// ========== 项目执行方分配 sub-resource ==========
@GetMapping("/{projectId}/assigns")
public AjaxResult getAssigns(@PathVariable("projectId") Long projectId)
{
return success(bizProjectAssignService.selectByProjectId(projectId));
}
@Log(title = "项目执行方分配", businessType = BusinessType.INSERT)
@PostMapping("/{projectId}/assigns")
public AjaxResult saveAssigns(@PathVariable("projectId") Long projectId, @RequestBody List<BizProjectAssign> assigns)
{
if (assigns == null) assigns = new ArrayList<>();
bizProjectAssignService.deleteByProjectId(projectId);
for (BizProjectAssign a : assigns) {
a.setProjectId(projectId);
if (a.getStatus() == null) a.setStatus("0");
bizProjectAssignService.insert(a);
}
return success();
}
@Log(title = "项目执行方分配", businessType = BusinessType.DELETE)
@DeleteMapping("/{projectId}/assigns")
public AjaxResult clearAssigns(@PathVariable("projectId") Long projectId)
{
return toAjax(bizProjectAssignService.deleteByProjectId(projectId));
}
/**
* 通用评分 upsert (任何角色: sponsor / executor / compliance)
* POST /business/project/rate
* 不做可见性校验 — 评分公开
*/
@Log(title = "项目评分", businessType = BusinessType.UPDATE)
@PostMapping("/rate")
public AjaxResult rate(@RequestBody BizProjectRating body)
{
if (body.getProjectId() == null || body.getRaterId() == null || body.getRaterRole() == null) {
return error("projectId / raterId / raterRole 必填");
}
body.setCreateBy(SecurityUtils.getUsername());
body.setUpdateBy(SecurityUtils.getUsername());
int rows = bizProjectRatingService.upsertRating(body);
return toAjax(rows);
}
/**
* 查某项目的所有评分 (公开, 任何角色可读)
* GET /business/project/ratings?projectId=X
*/
@GetMapping("/ratings")
public AjaxResult ratings(@RequestParam("projectId") Long projectId)
{
BizProjectRating q = new BizProjectRating();
q.setProjectId(projectId);
return success(bizProjectRatingService.selectList(q));
}
/**
* 赞助方分配监察员 (写 biz_project_sponsor_assign)
* POST /business/project/sponsorAssign
*/
@Log(title = "赞助方分配监察员", businessType = BusinessType.INSERT)
@PostMapping("/sponsorAssign")
public AjaxResult sponsorAssign(@RequestBody BizProjectSponsorAssign body)
{
body.setCreateBy(SecurityUtils.getUsername());
body.setSponsorUserId(SecurityUtils.getUserId());
int rows = bizProjectSponsorAssignService.insertAssign(body);
return toAjax(rows);
}
/**
* 赞助方批量分配监察员 (多个项目, 同一个监察员 + 同一份说明)
* POST /business/project/sponsorAssignBatch
* body: List<BizProjectSponsorAssign> (每个 item.projectId / monitorUserId / assignDesc / assignPoints)
*/
@Log(title = "赞助方批量分配监察员", businessType = BusinessType.INSERT)
@PostMapping("/sponsorAssignBatch")
public AjaxResult sponsorAssignBatch(@RequestBody List<BizProjectSponsorAssign> bodies)
{
if (bodies == null || bodies.isEmpty()) {
return error("请提供至少一个分配记录");
}
String loginName = SecurityUtils.getUsername();
Long loginUid = SecurityUtils.getUserId();
int ok = 0;
List<String> errors = new ArrayList<>();
for (int i = 0; i < bodies.size(); i++) {
BizProjectSponsorAssign body = bodies.get(i);
try {
if (body.getProjectId() == null || body.getMonitorUserId() == null) {
throw new IllegalArgumentException("projectId / monitorUserId 必填");
}
body.setCreateBy(loginName);
body.setSponsorUserId(loginUid);
bizProjectSponsorAssignService.insertAssign(body);
ok++;
} catch (Exception e) {
errors.add("" + (i + 1) + "条 (projectId=" + body.getProjectId() + "): " + e.getMessage());
}
}
AjaxResult ajax = success();
ajax.put("total", bodies.size());
ajax.put("ok", ok);
ajax.put("errors", errors);
return ajax;
}
}
@@ -0,0 +1,53 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.BizProjectPlan;
import com.ruoyi.business.service.IBizProjectPlanService;
/**
* 项目策划方案Controller
*/
@RestController
@RequestMapping("/business/projectPlan")
public class BizProjectPlanController extends BaseController
{
@Autowired
private IBizProjectPlanService BizProjectPlanService;
@GetMapping("/list")
public TableDataInfo list(BizProjectPlan BizProjectPlan)
{
startPage();
List<BizProjectPlan> list = BizProjectPlanService.selectList(BizProjectPlan);
return getDataTable(list);
}
@GetMapping("/{planId}")
public AjaxResult getInfo(@PathVariable("planId") String planId)
{
return success(BizProjectPlanService.getById(planId));
}
@Log(title = "项目策划方案", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizProjectPlan BizProjectPlan)
{
return toAjax(BizProjectPlanService.insert(BizProjectPlan));
}
@Log(title = "项目策划方案", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizProjectPlan BizProjectPlan)
{
return toAjax(BizProjectPlanService.updateByPrimaryKey(BizProjectPlan));
}
@Log(title = "项目策划方案", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(BizProjectPlanService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,71 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.BizProjectRating;
import com.ruoyi.business.service.IBizProjectRatingService;
/**
* 项目评分Controller
*/
@RestController
@RequestMapping("/business/projectRating")
public class BizProjectRatingController extends BaseController
{
@Autowired
private IBizProjectRatingService bizProjectRatingService;
@GetMapping("/list")
public TableDataInfo list(BizProjectRating bizProjectRating)
{
startPage();
List<BizProjectRating> list = bizProjectRatingService.selectList(bizProjectRating);
return getDataTable(list);
}
@GetMapping("/{ratingId}")
public AjaxResult getInfo(@PathVariable("ratingId") String ratingId)
{
return success(bizProjectRatingService.getById(ratingId));
}
@Log(title = "项目评分", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizProjectRating bizProjectRating)
{
return toAjax(bizProjectRatingService.insert(bizProjectRating));
}
/**
* 执行单位评分 upsert (按 project_id + rater_id + rater_role 唯一)
* POST /business/projectRating/rate
*/
@Log(title = "执行单位评分", businessType = BusinessType.UPDATE)
@PostMapping("/rate")
public AjaxResult rate(@RequestBody BizProjectRating body)
{
if (body.getProjectId() == null || body.getRaterId() == null || body.getRaterRole() == null) {
return error("projectId / raterId / raterRole 必填");
}
body.setCreateBy(getUsername());
body.setUpdateBy(getUsername());
int rows = bizProjectRatingService.upsertRating(body);
return toAjax(rows);
}
@Log(title = "项目评分", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizProjectRating bizProjectRating)
{
return toAjax(bizProjectRatingService.updateByPrimaryKey(bizProjectRating));
}
@Log(title = "项目评分", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizProjectRatingService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,74 @@
package com.ruoyi.business.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.business.domain.BizProject;
import com.ruoyi.business.domain.BizSupportLetter;
import com.ruoyi.business.domain.BizInvitation;
import com.ruoyi.business.domain.BizProjectPlan;
import com.ruoyi.business.service.IBizProjectService;
import com.ruoyi.business.service.IBizSupportLetterService;
import com.ruoyi.business.service.IBizInvitationService;
import com.ruoyi.business.service.IBizProjectPlanService;
/**
* 公开门户接口(无需登录)
*/
@RestController
@RequestMapping("/business/public")
public class BizPublicController extends BaseController {
@Autowired private IBizProjectService projectService;
@Autowired private IBizSupportLetterService supportLetterService;
@Autowired private IBizInvitationService invitationService;
@Autowired private IBizProjectPlanService projectPlanService;
@GetMapping("/index")
public AjaxResult index() {
Map<String, Object> map = new HashMap<>();
BizProject publishedQuery = new BizProject();
publishedQuery.setIsPublished("1");
List<BizProject> announcements = projectService.selectList(publishedQuery);
List<BizProjectPlan> plans = projectPlanService.selectList(new BizProjectPlan());
map.put("announcements", announcements);
map.put("plans", plans);
map.put("about", "北京整合医学学会(BAHIM)是一家专注于整合医学学术研究、项目合作与人才培养的省级学术组织。");
return success(map);
}
@GetMapping("/announcements")
public AjaxResult announcements() {
BizProject query = new BizProject();
query.setIsPublished("1");
List<BizProject> list = projectService.selectList(query);
return success(list);
}
@GetMapping("/project/{projectId}")
public AjaxResult projectDetail(@PathVariable String projectId) {
return success(projectService.getById(projectId));
}
@GetMapping("/supportLetter/{annId}")
public AjaxResult supportLetterDetail(@PathVariable String annId) {
return success(supportLetterService.getById(annId));
}
@GetMapping("/invitation/{annId}")
public AjaxResult invitationDetail(@PathVariable String annId) {
return success(invitationService.getById(annId));
}
@GetMapping("/apply")
public AjaxResult apply(String annId) {
return success();
}
}
@@ -0,0 +1,66 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.BizPublicity;
import com.ruoyi.business.service.IBizPublicityService;
import com.ruoyi.common.utils.SecurityUtils;
/**
* 项目公告Controller (与前端 bizList('publicity', ...) 对接)
*/
@RestController
@RequestMapping("/business/publicity")
public class BizPublicityController extends BaseController
{
@Autowired
private IBizPublicityService bizPublicityService;
@GetMapping("/list")
public TableDataInfo list(BizPublicity entity)
{
startPage();
// 按 project_id 过滤
entity.setStatus(null);
List<BizPublicity> list = bizPublicityService.selectList(entity);
return getDataTable(list);
}
@GetMapping("/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(bizPublicityService.getById(id));
}
@Log(title = "项目公告", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizPublicity entity)
{
entity.setCreateBy(SecurityUtils.getUsername());
entity.setUpdateBy(SecurityUtils.getUsername());
if (entity.getStatus() == null) entity.setStatus("1");
int rows = bizPublicityService.insert(entity);
return toAjax(rows);
}
@Log(title = "项目公告", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizPublicity entity)
{
entity.setUpdateBy(SecurityUtils.getUsername());
return toAjax(bizPublicityService.updateByPrimaryKey(entity));
}
@Log(title = "项目公告", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(bizPublicityService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,109 @@
package com.ruoyi.business.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.business.domain.BizExpert;
import com.ruoyi.business.dto.SmsValidForm;
import com.ruoyi.business.service.IBizExpertService;
import com.ruoyi.business.service.SysSmsService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.system.service.ISysUserService;
/**
* 专家注册 (完整实现)
* 流程:
* 1. 校验短信验证码
* 2. 检查用户名(=手机号)是否已注册
* 3. 加密密码
* 4. 插入 sys_user (role_type=doctor, user_type=01)
* 5. 插入 biz_expert (user_id 关联)
*/
@RestController
@RequestMapping("/business/auth")
public class BizRegisterController extends BaseController {
@Autowired
private SysSmsService smsService;
@Autowired
private ISysUserService userService;
@Autowired
private IBizExpertService expertService;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@PostMapping("/registerExpert")
public AjaxResult registerExpert(@RequestBody Map<String, Object> body) {
String realName = (String) body.get("realName");
String workUnit = (String) body.get("workUnit");
String department = (String) body.get("department");
String doctorTitle = (String) body.get("doctorTitle");
String phone = (String) body.get("phone");
String code = (String) body.get("code");
String password = (String) body.get("password");
String uuid = (String) body.get("uuid");
String licenseCertUrl = (String) body.get("licenseCertUrl");
String titleCertUrl = (String) body.get("titleCertUrl");
if (realName == null || realName.isEmpty()) return error("姓名不能为空");
if (workUnit == null || workUnit.isEmpty()) return error("工作单位不能为空");
if (phone == null || !phone.matches("^1\\d{10}$")) return error("手机号格式错误");
if (code == null || code.isEmpty()) return error("请输入短信验证码");
if (password == null || password.length() < 6 || password.length() > 20) return error("密码长度 6-20 位");
// 1. 校验短信验证码
SmsValidForm smsForm = new SmsValidForm();
smsForm.setPhone(phone);
smsForm.setSmsCode(code);
smsForm.setUuid(uuid);
try {
smsService.verifyCode(smsForm);
} catch (RuntimeException e) {
return error("验证码错误或已过期: " + e.getMessage());
}
// 2. 用户名=手机号, 检查是否已注册
if (userService.isPhoneRegistered(phone)) {
return error("该手机号已注册, 请直接登录");
}
// 3. 加密密码 + 4. 插入 sys_user (用户名=phone)
SysUser user = new SysUser();
user.setUserName(phone);
user.setNickName(realName);
user.setPhonenumber(phone);
user.setPassword(passwordEncoder.encode(password));
user.setStatus("0");
userService.insertUser(user);
Long userId = user.getUserId();
// sys_user.role_type 表字段 (DB 默认 executor, 专家需 = doctor), 用 mapper 更新
userService.updateRoleType(userId, "doctor");
// 5. 插入 biz_expert
BizExpert expert = new BizExpert();
expert.setExpertId(UUID.fastUUID().toString());
expert.setUserId(userId);
expert.setName(realName);
expert.setPhone(phone);
expert.setWorkUnit(workUnit);
expert.setDepartment(department);
expert.setTitle(doctorTitle);
expert.setPracticeCertUrl(licenseCertUrl);
expert.setTitleCertUrl(titleCertUrl);
expert.setAuditStatus("0");
expert.setStatus("0");
expertService.insert(expert);
return success("注册成功, 请等待审核").put("userId", userId);
}
}
@@ -0,0 +1,40 @@
package com.ruoyi.business.controller;
import com.ruoyi.business.service.SysSmsService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 注册专用 - 发送短信验证码
* 校验: 手机号未被注册过, 否则报错
* 匿名访问 (前端 register-* 页面调用, 登录前)
*/
@RestController
@RequestMapping("/business/auth")
public class BizRegisterSmsController extends BaseController {
@Autowired
private SysSmsService smsService;
@Autowired
private com.ruoyi.system.service.ISysUserService userService;
@PostMapping("/registerSendSms")
public AjaxResult registerSendSms(@RequestBody Map<String, String> body) {
String phone = body == null ? null : body.get("phone");
if (phone == null || !phone.matches("^1\\d{10}$")) {
return error("请输入正确的手机号");
}
// 手机号已注册则报错
if (userService.isPhoneRegistered(phone)) {
return error("该手机号已注册, 请直接登录");
}
String uuid = smsService.sendCode(phone);
return AjaxResult.success("验证码已发送", uuid);
}
}
@@ -0,0 +1,53 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.BizResource;
import com.ruoyi.business.service.IBizResourceService;
/**
* 资源Controller
*/
@RestController
@RequestMapping("/business/resource")
public class BizResourceController extends BaseController
{
@Autowired
private IBizResourceService bizResourceService;
@GetMapping("/list")
public TableDataInfo list(BizResource bizResource)
{
startPage();
List<BizResource> list = bizResourceService.selectList(bizResource);
return getDataTable(list);
}
@GetMapping("/{resourceId}")
public AjaxResult getInfo(@PathVariable("resourceId") String resourceId)
{
return success(bizResourceService.getById(resourceId));
}
@Log(title = "资源", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizResource bizResource)
{
return toAjax(bizResourceService.insert(bizResource));
}
@Log(title = "资源", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizResource bizResource)
{
return toAjax(bizResourceService.updateByPrimaryKey(bizResource));
}
@Log(title = "资源", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizResourceService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,79 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.business.domain.BizSubmission;
import com.ruoyi.business.enums.SubmissionStatus;
import com.ruoyi.business.service.IBizSubmissionService;
/**
* 投稿Controller
*/
@RestController
@RequestMapping("/business/submission")
public class BizSubmissionController extends BaseController
{
@Autowired
private IBizSubmissionService bizSubmissionService;
@GetMapping("/list")
public TableDataInfo list(BizSubmission bizSubmission)
{
// 后端兜底: 只查当前登录用户提交的; admin 跳过此限制
if (!SecurityUtils.isAdmin()) {
bizSubmission.setSubmitterId(SecurityUtils.getUserId());
}
startPage();
List<BizSubmission> list = bizSubmissionService.selectList(bizSubmission);
return getDataTable(list);
}
@GetMapping("/{submissionId}")
public AjaxResult getInfo(@PathVariable("submissionId") String submissionId)
{
return success(bizSubmissionService.getById(submissionId));
}
@Log(title = "投稿", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizSubmission bizSubmission)
{
// 后端兜底: 强制写入当前登录用户, 防止前端漏传/绕过导致列表过滤查不到
bizSubmission.setSubmitterId(SecurityUtils.getUserId());
bizSubmission.setSubmitterName(SecurityUtils.getUsername());
bizSubmission.setCreateBy(getUsername());
bizSubmission.setUpdateBy(getUsername());
// 状态: 新建默认 DRAFT(待提交); 校验必须是英文 code 之一
if (bizSubmission.getStatus() == null || bizSubmission.getStatus().isEmpty()) {
bizSubmission.setStatus(SubmissionStatus.DRAFT.getCode());
} else if (!SubmissionStatus.isValid(bizSubmission.getStatus())) {
return AjaxResult.error("状态值非法: " + bizSubmission.getStatus());
}
return toAjax(bizSubmissionService.insert(bizSubmission));
}
@Log(title = "投稿", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizSubmission bizSubmission)
{
// 修改时也强制覆盖 submitterId/submitterName, 防止越权篡改为他人
bizSubmission.setSubmitterId(SecurityUtils.getUserId());
bizSubmission.setSubmitterName(SecurityUtils.getUsername());
bizSubmission.setUpdateBy(getUsername());
// 状态校验 (英文 code)
if (bizSubmission.getStatus() != null && !bizSubmission.getStatus().isEmpty()
&& !SubmissionStatus.isValid(bizSubmission.getStatus())) {
return AjaxResult.error("状态值非法: " + bizSubmission.getStatus());
}
return toAjax(bizSubmissionService.updateByPrimaryKey(bizSubmission));
}
@Log(title = "投稿", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizSubmissionService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,53 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.BizSupportIntent;
import com.ruoyi.business.service.IBizSupportIntentService;
/**
* 支持意向Controller
*/
@RestController
@RequestMapping("/business/supportIntent")
public class BizSupportIntentController extends BaseController
{
@Autowired
private IBizSupportIntentService bizSupportIntentService;
@GetMapping("/list")
public TableDataInfo list(BizSupportIntent bizSupportIntent)
{
startPage();
List<BizSupportIntent> list = bizSupportIntentService.selectList(bizSupportIntent);
return getDataTable(list);
}
@GetMapping("/{intentId}")
public AjaxResult getInfo(@PathVariable("intentId") String intentId)
{
return success(bizSupportIntentService.getById(intentId));
}
@Log(title = "支持意向", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizSupportIntent bizSupportIntent)
{
return toAjax(bizSupportIntentService.insert(bizSupportIntent));
}
@Log(title = "支持意向", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizSupportIntent bizSupportIntent)
{
return toAjax(bizSupportIntentService.updateByPrimaryKey(bizSupportIntent));
}
@Log(title = "支持意向", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizSupportIntentService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,53 @@
package com.ruoyi.business.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.BizSupportLetter;
import com.ruoyi.business.service.IBizSupportLetterService;
/**
* 支持函Controller
*/
@RestController
@RequestMapping("/business/supportLetter")
public class BizSupportLetterController extends BaseController
{
@Autowired
private IBizSupportLetterService bizSupportLetterService;
@GetMapping("/list")
public TableDataInfo list(BizSupportLetter bizSupportLetter)
{
startPage();
List<BizSupportLetter> list = bizSupportLetterService.selectList(bizSupportLetter);
return getDataTable(list);
}
@GetMapping("/{letterId}")
public AjaxResult getInfo(@PathVariable("letterId") String letterId)
{
return success(bizSupportLetterService.getById(letterId));
}
@Log(title = "支持函", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody BizSupportLetter bizSupportLetter)
{
return toAjax(bizSupportLetterService.insert(bizSupportLetter));
}
@Log(title = "支持函", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BizSupportLetter bizSupportLetter)
{
return toAjax(bizSupportLetterService.updateByPrimaryKey(bizSupportLetter));
}
@Log(title = "支持函", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(bizSupportLetterService.deleteByPrimaryKeys(ids));
}
}
@@ -0,0 +1,41 @@
package com.ruoyi.business.controller;
import com.ruoyi.business.dto.SmsValidForm;
import com.ruoyi.business.service.SysSmsService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 短信验证码接口
* 参考 hwt-code BizAuthApi.sendSmsOnLogin 模式
*/
@RestController
@RequestMapping("/business/sms")
public class SmsController extends BaseController {
@Autowired
private SysSmsService smsService;
/** 发送验证码, 返回 uuid (前端 form 校验时回传) */
@GetMapping("/send")
public AjaxResult send(@RequestParam(required = false) String phone) {
if (phone == null || phone.trim().isEmpty()) {
return error("手机号码不能为空");
}
String uuid = smsService.sendCode(phone);
return AjaxResult.success("ok", uuid);
}
/** 校验验证码 */
@PostMapping("/verify")
public AjaxResult verify(@RequestBody SmsValidForm form) {
try {
smsService.verifyCode(form);
} catch (RuntimeException e) {
return error(e.getMessage());
}
return success("ok");
}
}
@@ -0,0 +1,35 @@
package com.ruoyi.business.domain;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 科室字典 */
public class BizDepartment extends BaseEntity
{
private static final long serialVersionUID = 1L;
@Excel(name = "ID")
private Long deptId;
@Excel(name = "科室名称")
private String name;
@Excel(name = "排序")
private Integer sort;
/** 0=启用 1=停用 */
@Excel(name = "状态", readConverterExp = "0=启用,1=停用")
private String status;
public Long getDeptId() { return deptId; }
public void setDeptId(Long deptId) { this.deptId = deptId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getSort() { return sort; }
public void setSort(Integer sort) { this.sort = sort; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
}
@@ -0,0 +1,35 @@
package com.ruoyi.business.domain;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 医生职称字典 */
public class BizDoctorTitle extends BaseEntity
{
private static final long serialVersionUID = 1L;
@Excel(name = "ID")
private Long titleId;
@Excel(name = "职称名称")
private String name;
@Excel(name = "排序")
private Integer sort;
/** 0=启用 1=停用 */
@Excel(name = "状态", readConverterExp = "0=启用,1=停用")
private String status;
public Long getTitleId() { return titleId; }
public void setTitleId(Long titleId) { this.titleId = titleId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getSort() { return sort; }
public void setSort(Integer sort) { this.sort = sort; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
}
@@ -0,0 +1,82 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 执行意向对象 BizExecutionIntent */
public class BizExecutionIntent extends BaseEntity {
private static final long serialVersionUID = 1L;
/** intentId */
private String intentId;
/** 用户ID (关联 sys_user.user_id) */
private Long userId;
/** project_no */
@Excel(name = "project_no")
private String projectNo;
/** project_name */
@Excel(name = "project_name")
private String projectName;
/** name */
@Excel(name = "name")
private String name;
/** work_unit */
@Excel(name = "work_unit")
private String workUnit;
/** department */
@Excel(name = "department")
private String department;
/** position */
@Excel(name = "position")
private String position;
/** phone */
@Excel(name = "phone")
private String phone;
/** onboard_status */
@Excel(name = "onboard_status")
private String onboardStatus;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
public String getIntentId() { return intentId; }
public void setIntentId(String intentId) { this.intentId = intentId; }
public Long getUserId() { return userId; }
public void setUserId(Long userId) { this.userId = userId; }
public String getProjectNo() { return projectNo; }
public void setProjectNo(String projectNo) { this.projectNo = projectNo; }
public String getProjectName() { return projectName; }
public void setProjectName(String projectName) { this.projectName = projectName; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getWorkUnit() { return workUnit; }
public void setWorkUnit(String workUnit) { this.workUnit = workUnit; }
public String getDepartment() { return department; }
public void setDepartment(String department) { this.department = department; }
public String getPosition() { return position; }
public void setPosition(String position) { this.position = position; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
public String getOnboardStatus() { return onboardStatus; }
public void setOnboardStatus(String onboardStatus) { this.onboardStatus = onboardStatus; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}
@@ -0,0 +1,137 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 专家对象 BizExpert */
public class BizExpert extends BaseEntity {
private static final long serialVersionUID = 1L;
/** expertId */
private String expertId;
/** name */
@Excel(name = "name")
private String name;
/** phone */
@Excel(name = "phone")
private String phone;
/** work_unit */
@Excel(name = "work_unit")
private String workUnit;
/** department */
@Excel(name = "department")
private String department;
/** title */
@Excel(name = "title")
private String title;
/** practice_cert_url */
@Excel(name = "practice_cert_url")
private String practiceCertUrl;
/** title_cert_url */
@Excel(name = "title_cert_url")
private String titleCertUrl;
/** audit_status */
@Excel(name = "audit_status")
private String auditStatus;
/** audit_by */
@Excel(name = "audit_by")
private String auditBy;
/** audit_time */
@Excel(name = "audit_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date auditTime;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 关联系统用户ID */
private Long userId;
/** 地区 */
private String region;
/** 证件号码 */
private String idCard;
/** 银行卡号 */
private String bankCard;
/** 银行名称 */
private String bankName;
/** 开户行省份 */
private String bankProvince;
/** 开户行城市 */
private String bankCity;
/** 开户行地址 */
private String bankAddress;
/** 身份证正面URL */
private String idCardFrontUrl;
/** 身份证反面URL */
private String idCardBackUrl;
/** 审核意见 */
private String auditOpinion;
/** 状态 0正常 1禁用 */
private String status;
public String getExpertId() { return expertId; }
public void setExpertId(String expertId) { this.expertId = expertId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
public String getWorkUnit() { return workUnit; }
public void setWorkUnit(String workUnit) { this.workUnit = workUnit; }
public String getDepartment() { return department; }
public void setDepartment(String department) { this.department = department; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getPracticeCertUrl() { return practiceCertUrl; }
public void setPracticeCertUrl(String practiceCertUrl) { this.practiceCertUrl = practiceCertUrl; }
public String getTitleCertUrl() { return titleCertUrl; }
public void setTitleCertUrl(String titleCertUrl) { this.titleCertUrl = titleCertUrl; }
public String getAuditStatus() { return auditStatus; }
public void setAuditStatus(String auditStatus) { this.auditStatus = auditStatus; }
public String getAuditBy() { return auditBy; }
public void setAuditBy(String auditBy) { this.auditBy = auditBy; }
public Date getAuditTime() { return auditTime; }
public void setAuditTime(Date auditTime) { this.auditTime = auditTime; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
public Long getUserId() { return userId; }
public void setUserId(Long userId) { this.userId = userId; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getAuditOpinion() { return auditOpinion; }
public void setAuditOpinion(String auditOpinion) { this.auditOpinion = auditOpinion; }
public String getRegion() { return region; }
public void setRegion(String region) { this.region = region; }
public String getIdCard() { return idCard; }
public void setIdCard(String idCard) { this.idCard = idCard; }
public String getBankCard() { return bankCard; }
public void setBankCard(String bankCard) { this.bankCard = bankCard; }
public String getBankName() { return bankName; }
public void setBankName(String bankName) { this.bankName = bankName; }
public String getBankProvince() { return bankProvince; }
public void setBankProvince(String bankProvince) { this.bankProvince = bankProvince; }
public String getBankCity() { return bankCity; }
public void setBankCity(String bankCity) { this.bankCity = bankCity; }
public String getBankAddress() { return bankAddress; }
public void setBankAddress(String bankAddress) { this.bankAddress = bankAddress; }
public String getIdCardFrontUrl() { return idCardFrontUrl; }
public void setIdCardFrontUrl(String idCardFrontUrl) { this.idCardFrontUrl = idCardFrontUrl; }
public String getIdCardBackUrl() { return idCardBackUrl; }
public void setIdCardBackUrl(String idCardBackUrl) { this.idCardBackUrl = idCardBackUrl; }
}
@@ -0,0 +1,78 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 邀请函对象 BizInvitation */
public class BizInvitation extends BaseEntity {
private static final long serialVersionUID = 1L;
/** annId */
private String annId;
/** title */
@Excel(name = "title")
private String title;
/** meeting_name */
@Excel(name = "meeting_name")
private String meetingName;
/** expert_name */
@Excel(name = "expert_name")
private String expertName;
/** content */
@Excel(name = "content")
private String content;
/** issue_date */
@Excel(name = "issue_date")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date issueDate;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 邀请函ID */
private Long inviteId;
/** 项目ID */
private Long projectId;
/** 项目编号 */
private String projectNo;
/** 邀请函模板URL */
private String templateUrl;
/** 二维码URL */
private String qrCodeUrl;
/** 分享URL */
private String shareUrl;
/** 发布时间 */
private String publishTime;
public String getAnnId() { return annId; }
public void setAnnId(String annId) { this.annId = annId; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getMeetingName() { return meetingName; }
public void setMeetingName(String meetingName) { this.meetingName = meetingName; }
public String getExpertName() { return expertName; }
public void setExpertName(String expertName) { this.expertName = expertName; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
public Date getIssueDate() { return issueDate; }
public void setIssueDate(Date issueDate) { this.issueDate = issueDate; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}
@@ -0,0 +1,87 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 劳务凭证对象 BizLaborVoucher */
public class BizLaborVoucher extends BaseEntity {
private static final long serialVersionUID = 1L;
/** voucherId */
private String voucherId;
/** voucher_no */
@Excel(name = "voucher_no")
private String voucherNo;
/** meeting_name */
@Excel(name = "meeting_name")
private String meetingName;
/** expert_name */
@Excel(name = "expert_name")
private String expertName;
/** id_card */
@Excel(name = "id_card")
private String idCard;
/** bank_account */
@Excel(name = "bank_account")
private String bankAccount;
/** amount */
@Excel(name = "amount")
private BigDecimal amount;
/** submit_date */
@Excel(name = "submit_date")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date submitDate;
/** audit_status */
@Excel(name = "audit_status")
private String auditStatus;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 会议ID */
private Long meetingId;
/** 审核意见 */
private String auditOpinion;
/** 审核人 */
private String auditBy;
/** 审核时间 */
private String auditTime;
public String getVoucherId() { return voucherId; }
public void setVoucherId(String voucherId) { this.voucherId = voucherId; }
public String getVoucherNo() { return voucherNo; }
public void setVoucherNo(String voucherNo) { this.voucherNo = voucherNo; }
public String getMeetingName() { return meetingName; }
public void setMeetingName(String meetingName) { this.meetingName = meetingName; }
public String getExpertName() { return expertName; }
public void setExpertName(String expertName) { this.expertName = expertName; }
public String getIdCard() { return idCard; }
public void setIdCard(String idCard) { this.idCard = idCard; }
public String getBankAccount() { return bankAccount; }
public void setBankAccount(String bankAccount) { this.bankAccount = bankAccount; }
public BigDecimal getAmount() { return amount; }
public void setAmount(BigDecimal amount) { this.amount = amount; }
public Date getSubmitDate() { return submitDate; }
public void setSubmitDate(Date submitDate) { this.submitDate = submitDate; }
public String getAuditStatus() { return auditStatus; }
public void setAuditStatus(String auditStatus) { this.auditStatus = auditStatus; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}
@@ -0,0 +1,103 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 会议对象 BizMeeting */
public class BizMeeting extends BaseEntity {
private static final long serialVersionUID = 1L;
/** meetingId */
private String meetingId;
/** project_no */
@Excel(name = "project_no")
private String projectNo;
/** business_id */
@Excel(name = "business_id")
private String businessId;
/** project_form */
@Excel(name = "project_form")
private String projectForm;
/** meeting_name */
@Excel(name = "meeting_name")
private String meetingName;
/** start_time */
@Excel(name = "start_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/** end_time */
@Excel(name = "end_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/** total_periods */
@Excel(name = "total_periods")
private Long totalPeriods;
/** period_no */
@Excel(name = "period_no")
private Long periodNo;
/** current_stage */
@Excel(name = "current_stage")
private String currentStage;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 所属项目ID */
private Long projectId;
/** 项目名称 */
private String projectName;
/** 所属公司名称 (冗余字段, 由 biz_project.org_name 同步) */
private String orgName;
/** 监察意见 */
private String supervisionOpinion;
/** 监察人 */
private String supervisionBy;
/** 监察时间 */
private String supervisionTime;
/** 邀请函URL */
private String invitationUrl;
/** 日程海报URL */
private String scheduleUrl;
/** 签署劳务 0未签 1已签 */
private String laborSigned;
public String getMeetingId() { return meetingId; }
public void setMeetingId(String meetingId) { this.meetingId = meetingId; }
public String getProjectNo() { return projectNo; }
public void setProjectNo(String projectNo) { this.projectNo = projectNo; }
public String getBusinessId() { return businessId; }
public void setBusinessId(String businessId) { this.businessId = businessId; }
public String getProjectForm() { return projectForm; }
public void setProjectForm(String projectForm) { this.projectForm = projectForm; }
public String getMeetingName() { return meetingName; }
public void setMeetingName(String meetingName) { this.meetingName = meetingName; }
public Date getStartTime() { return startTime; }
public void setStartTime(Date startTime) { this.startTime = startTime; }
public Date getEndTime() { return endTime; }
public void setEndTime(Date endTime) { this.endTime = endTime; }
public Long getTotalPeriods() { return totalPeriods; }
public void setTotalPeriods(Long totalPeriods) { this.totalPeriods = totalPeriods; }
public Long getPeriodNo() { return periodNo; }
public void setPeriodNo(Long periodNo) { this.periodNo = periodNo; }
public String getCurrentStage() { return currentStage; }
public void setCurrentStage(String currentStage) { this.currentStage = currentStage; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}
@@ -0,0 +1,87 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 会议结算明细对象 BizMeetingSettlement */
public class BizMeetingSettlement extends BaseEntity {
private static final long serialVersionUID = 1L;
/** id */
private String id;
/** project_no */
@Excel(name = "project_no")
private String projectNo;
/** meeting_id */
@Excel(name = "meeting_id")
private Long meetingId;
/** fee_type */
@Excel(name = "fee_type")
private String feeType;
/** unit_price */
@Excel(name = "unit_price")
private BigDecimal unitPrice;
/** qty */
@Excel(name = "qty")
private Long qty;
/** subtotal */
@Excel(name = "subtotal")
private BigDecimal subtotal;
/** remark */
@Excel(name = "remark")
private String remark;
/** audit_status */
@Excel(name = "audit_status")
private String auditStatus;
/** settlement_type */
@Excel(name = "settlement_type")
private String settlementType;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 会议名称 */
private String projectName;
/** 执行单位 */
private String execUnit;
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getProjectNo() { return projectNo; }
public void setProjectNo(String projectNo) { this.projectNo = projectNo; }
public Long getMeetingId() { return meetingId; }
public void setMeetingId(Long meetingId) { this.meetingId = meetingId; }
public String getFeeType() { return feeType; }
public void setFeeType(String feeType) { this.feeType = feeType; }
public BigDecimal getUnitPrice() { return unitPrice; }
public void setUnitPrice(BigDecimal unitPrice) { this.unitPrice = unitPrice; }
public Long getQty() { return qty; }
public void setQty(Long qty) { this.qty = qty; }
public BigDecimal getSubtotal() { return subtotal; }
public void setSubtotal(BigDecimal subtotal) { this.subtotal = subtotal; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public String getAuditStatus() { return auditStatus; }
public void setAuditStatus(String auditStatus) { this.auditStatus = auditStatus; }
public String getSettlementType() { return settlementType; }
public void setSettlementType(String settlementType) { this.settlementType = settlementType; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}
@@ -0,0 +1,78 @@
package com.ruoyi.business.domain;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 个人通知消息对象 biz_message */
public class BizMessage extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** msg_id */
private Long msgId;
/** 接收人 user_id */
@Excel(name = "接收人")
private Long receiverUserId;
/** 接收人姓名 (联表显示) */
@Excel(name = "接收人")
private String receiverName;
/** 消息类型 1通知 2待办 3系统 */
@Excel(name = "类型")
private String msgType;
/** 标题 */
@Excel(name = "标题")
private String title;
/** 内容 */
private String content;
/** 业务类型 auth/project/meeting/agreement */
private String bizType;
/** 关联业务ID */
private Long bizId;
/** 已读 0否 1是 */
@Excel(name = "已读")
private String isRead;
/** 已读时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date readTime;
public Long getMsgId() { return msgId; }
public void setMsgId(Long msgId) { this.msgId = msgId; }
public Long getReceiverUserId() { return receiverUserId; }
public void setReceiverUserId(Long receiverUserId) { this.receiverUserId = receiverUserId; }
public String getReceiverName() { return receiverName; }
public void setReceiverName(String receiverName) { this.receiverName = receiverName; }
public String getMsgType() { return msgType; }
public void setMsgType(String msgType) { this.msgType = msgType; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
public String getBizType() { return bizType; }
public void setBizType(String bizType) { this.bizType = bizType; }
public Long getBizId() { return bizId; }
public void setBizId(Long bizId) { this.bizId = bizId; }
public String getIsRead() { return isRead; }
public void setIsRead(String isRead) { this.isRead = isRead; }
public Date getReadTime() { return readTime; }
public void setReadTime(Date readTime) { this.readTime = readTime; }
}
@@ -0,0 +1,75 @@
package com.ruoyi.business.domain;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 公司对象 biz_org
* 用途: 赞助方(sponsor) + 执行方(execution) 共用
* 重构说明: 原 biz_support_unit + biz_execution_unit 合并, 通过 org_type 区分
*/
public class BizOrg extends BaseEntity {
private static final long serialVersionUID = 1L;
/** org_id */
private Long orgId;
/** org_name */
@Excel(name = "org_name")
private String orgName;
/** org_type: sponsor赞助方 / execution执行方 */
@Excel(name = "org_type")
private String orgType;
/** 企业性质 私营/国营/中外合资/外资/其他 */
@Excel(name = "business_nature")
private String businessNature;
/** address */
@Excel(name = "address")
private String address;
/** tax_no */
@Excel(name = "tax_no")
private String taxNo;
/** contact_name */
@Excel(name = "contact_name")
private String contactName;
/** contact_phone */
@Excel(name = "contact_phone")
private String contactPhone;
/** intent_count (仅赞助方用) */
@Excel(name = "intent_count")
private Integer intentCount;
/** status */
@Excel(name = "status")
private String status;
/** create_time */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_time */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
public Long getOrgId() { return orgId; }
public void setOrgId(Long orgId) { this.orgId = orgId; }
public String getOrgName() { return orgName; }
public void setOrgName(String orgName) { this.orgName = orgName; }
public String getOrgType() { return orgType; }
public void setOrgType(String orgType) { this.orgType = orgType; }
public String getBusinessNature() { return businessNature; }
public void setBusinessNature(String businessNature) { this.businessNature = businessNature; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
public String getTaxNo() { return taxNo; }
public void setTaxNo(String taxNo) { this.taxNo = taxNo; }
public String getContactName() { return contactName; }
public void setContactName(String contactName) { this.contactName = contactName; }
public String getContactPhone() { return contactPhone; }
public void setContactPhone(String contactPhone) { this.contactPhone = contactPhone; }
public Integer getIntentCount() { return intentCount; }
public void setIntentCount(Integer intentCount) { this.intentCount = intentCount; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}
@@ -0,0 +1,108 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 人员对象 BizPerson */
public class BizPerson extends BaseEntity {
private static final long serialVersionUID = 1L;
/** personId */
private String personId;
/** name */
@Excel(name = "name")
private String name;
/** phone */
@Excel(name = "phone")
private String phone;
/** 所属公司ID (FK: biz_org.org_id) */
private Long orgId;
/** 所属公司名 (LEFT JOIN biz_org, 仅展示, 不入库) */
private String orgName;
/** 所属公司类型 (LEFT JOIN biz_org, 仅展示, 不入库) */
private String orgType;
/** department */
@Excel(name = "department")
private String department;
/** position */
@Excel(name = "position")
private String position;
/** role */
@Excel(name = "role")
private String role;
/** status */
@Excel(name = "status")
private String status;
/** 逻辑删除 0正常 1已删 */
private String delFlag;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 关联系统用户ID */
private Long userId;
/** 所属单位类型 execution执行/sponsor支持 */
private String unitType;
/** 账号类型 (来自 sys_user.account_type, MAIN=主账号 / SUB=子账号) - 仅展示用,不入库 */
private String accountType;
/** 主账号ID (来自 sys_user.parent_user_id, 子账号指向其主账号) - 仅展示用 */
private Long parentUserId;
/** 子账号登录账号 (前端传入, 用于创建 sys_user 子账号) - 非持久化字段 */
private transient String loginUsername;
/** 子账号初始密码 (前端传入, 明文, 创建后不存储明文) - 非持久化字段 */
private transient String loginPassword;
public String getPersonId() { return personId; }
public void setPersonId(String personId) { this.personId = personId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
public Long getOrgId() { return orgId; }
public void setOrgId(Long orgId) { this.orgId = orgId; }
public String getOrgName() { return orgName; }
public void setOrgName(String orgName) { this.orgName = orgName; }
public String getOrgType() { return orgType; }
public void setOrgType(String orgType) { this.orgType = orgType; }
public String getDepartment() { return department; }
public void setDepartment(String department) { this.department = department; }
public String getPosition() { return position; }
public void setPosition(String position) { this.position = position; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getDelFlag() { return delFlag; }
public void setDelFlag(String delFlag) { this.delFlag = delFlag; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
public Long getUserId() { return userId; }
public void setUserId(Long userId) { this.userId = userId; }
public String getUnitType() { return unitType; }
public void setUnitType(String unitType) { this.unitType = unitType; }
public String getAccountType() { return accountType; }
public void setAccountType(String accountType) { this.accountType = accountType; }
public Long getParentUserId() { return parentUserId; }
public void setParentUserId(Long parentUserId) { this.parentUserId = parentUserId; }
public String getLoginUsername() { return loginUsername; }
public void setLoginUsername(String loginUsername) { this.loginUsername = loginUsername; }
public String getLoginPassword() { return loginPassword; }
public void setLoginPassword(String loginPassword) { this.loginPassword = loginPassword; }
}
@@ -0,0 +1,51 @@
package com.ruoyi.business.domain;
import com.ruoyi.common.annotation.Excel;
/**
* sponsor 端人员批量导入 VO (中文列头, 用 ruoyi ExcelUtil 解析)
*
* <p>区别于 BizPerson 实体: 这里只暴露用户能填写的业务字段, 不包含内部 id/审计字段,
* 列头按原型 sponsor-new-person.html: 姓名/手机号/所属公司/部门/职务/角色/状态.
*
* <p>导入后端会按以下规则创建 sys_user 子账号 (parent_user_id=当前登录主账号):
* <ul>
* <li>loginUsername = 手机号 (要求唯一)</li>
* <li>loginPassword = "123456" (默认密码, 前端 toast 提示用户)</li>
* <li>unitType = "sponsor"</li>
* <li>orgId = 业务层按 orgName 查 biz_org 取 org_id (TODO: SponsorPeople 那边 import 接口需补这步)</li>
* </ul>
*/
public class BizPersonImportVO
{
@Excel(name = "姓名", sort = 1)
private String name;
@Excel(name = "手机号", sort = 2)
private String phone;
@Excel(name = "所属公司", sort = 3)
private String orgName;
@Excel(name = "部门", sort = 4)
private String department;
@Excel(name = "职务", sort = 5)
private String position;
@Excel(name = "角色", sort = 6)
private String role;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
public String getOrgName() { return orgName; }
public void setOrgName(String orgName) { this.orgName = orgName; }
public String getDepartment() { return department; }
public void setDepartment(String department) { this.department = department; }
public String getPosition() { return position; }
public void setPosition(String position) { this.position = position; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
}
@@ -0,0 +1,212 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 项目对象 BizProject */
public class BizProject extends BaseEntity {
private static final long serialVersionUID = 1L;
/** projectId */
private String projectId;
/** project_no */
@Excel(name = "project_no")
private String projectNo;
/** project_name */
@Excel(name = "project_name")
private String projectName;
/** total_sessions */
@Excel(name = "total_sessions")
private Long totalSessions;
/** done_sessions */
@Excel(name = "done_sessions")
private Long doneSessions;
/** todo_sessions */
@Excel(name = "todo_sessions")
private Long todoSessions;
/** total_amount */
@Excel(name = "total_amount")
private BigDecimal totalAmount;
/** available_amount */
@Excel(name = "available_amount")
private BigDecimal availableAmount;
/** paid_labor_amount */
@Excel(name = "paid_labor_amount")
private BigDecimal paidLaborAmount;
/** paid_meeting_amount */
@Excel(name = "paid_meeting_amount")
private BigDecimal paidMeetingAmount;
/** rating_score (平均分) */
@Excel(name = "rating_score")
private BigDecimal ratingScore;
/** 评分维度: 履约质量 */
private BigDecimal ratingQ1;
/** 评分维度: 时效响应 */
private BigDecimal ratingQ2;
/** 评分维度: 配合度 */
private BigDecimal ratingQ3;
/** 评分维度: 合规安全 */
private BigDecimal ratingQ4;
/** org_name (赞助方/执行方, 由 org_type 区分) */
@Excel(name = "org_name")
private String orgName;
/** org_type: sponsor 赞助方 / execution 执行方 */
@Excel(name = "org_type")
private String orgType;
/** project_form */
@Excel(name = "project_form")
private String projectForm;
/** is_finished */
@Excel(name = "is_finished")
private String isFinished;
/** is_settled */
@Excel(name = "is_settled")
private String isSettled;
/** org_id (赞助方/执行方, 由 org_type 区分) */
@Excel(name = "org_id")
private Long orgId;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 管理费及税金 */
private BigDecimal manageFee;
/** 项目开始时间 */
private String startTime;
/** 项目结束时间 */
private String endTime;
/** 提交材料截止天数 */
private Integer submitDeadlineDays;
/** 支持合同文件URL */
private String supportContractUrl;
/** 执行合同文件URL */
private String executeContractUrl;
/** 邀请函文件URL */
private String invitationUrl;
/** 支持函文件URL */
private String supportLetterUrl;
/** 已发布公告URL */
private String publishUrl;
/** 通知文件URL */
private String noticeUrl;
/** 日程文件URL */
private String scheduleUrl;
/** 是否已发布公示 0否 1是 */
private String isPublished;
/** 发布时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date publishTime;
/** 公告类型 (邀请函/支持函/通知/日程/公示) */
private String announcementType;
/* ============ 赞助方评分字段 (来自 biz_project_sponsor 中间表, 仅展示用) ============ */
/** 当前 login 用户对该项目的平均分 */
private BigDecimal sponsorRating;
private Integer sponsorQ1;
private Integer sponsorQ2;
private Integer sponsorQ3;
private Integer sponsorQ4;
private String sponsorRemark;
public String getProjectId() { return projectId; }
public void setProjectId(String projectId) { this.projectId = projectId; }
public String getProjectNo() { return projectNo; }
public void setProjectNo(String projectNo) { this.projectNo = projectNo; }
public String getProjectName() { return projectName; }
public void setProjectName(String projectName) { this.projectName = projectName; }
public Long getTotalSessions() { return totalSessions; }
public void setTotalSessions(Long totalSessions) { this.totalSessions = totalSessions; }
public Long getDoneSessions() { return doneSessions; }
public void setDoneSessions(Long doneSessions) { this.doneSessions = doneSessions; }
public Long getTodoSessions() { return todoSessions; }
public void setTodoSessions(Long todoSessions) { this.todoSessions = todoSessions; }
public BigDecimal getTotalAmount() { return totalAmount; }
public void setTotalAmount(BigDecimal totalAmount) { this.totalAmount = totalAmount; }
public BigDecimal getAvailableAmount() { return availableAmount; }
public void setAvailableAmount(BigDecimal availableAmount) { this.availableAmount = availableAmount; }
public BigDecimal getPaidLaborAmount() { return paidLaborAmount; }
public void setPaidLaborAmount(BigDecimal paidLaborAmount) { this.paidLaborAmount = paidLaborAmount; }
public BigDecimal getPaidMeetingAmount() { return paidMeetingAmount; }
public void setPaidMeetingAmount(BigDecimal paidMeetingAmount) { this.paidMeetingAmount = paidMeetingAmount; }
public BigDecimal getRatingScore() { return ratingScore; }
public void setRatingScore(BigDecimal ratingScore) { this.ratingScore = ratingScore; }
public BigDecimal getRatingQ1() { return ratingQ1; }
public void setRatingQ1(BigDecimal ratingQ1) { this.ratingQ1 = ratingQ1; }
public BigDecimal getRatingQ2() { return ratingQ2; }
public void setRatingQ2(BigDecimal ratingQ2) { this.ratingQ2 = ratingQ2; }
public BigDecimal getRatingQ3() { return ratingQ3; }
public void setRatingQ3(BigDecimal ratingQ3) { this.ratingQ3 = ratingQ3; }
public BigDecimal getRatingQ4() { return ratingQ4; }
public void setRatingQ4(BigDecimal ratingQ4) { this.ratingQ4 = ratingQ4; }
public String getOrgName() { return orgName; }
public void setOrgName(String orgName) { this.orgName = orgName; }
public String getOrgType() { return orgType; }
public void setOrgType(String orgType) { this.orgType = orgType; }
public String getProjectForm() { return projectForm; }
public void setProjectForm(String projectForm) { this.projectForm = projectForm; }
public String getIsFinished() { return isFinished; }
public void setIsFinished(String isFinished) { this.isFinished = isFinished; }
public String getIsSettled() { return isSettled; }
public void setIsSettled(String isSettled) { this.isSettled = isSettled; }
public Long getOrgId() { return orgId; }
public void setOrgId(Long orgId) { this.orgId = orgId; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
public BigDecimal getManageFee() { return manageFee; }
public void setManageFee(BigDecimal manageFee) { this.manageFee = manageFee; }
public String getStartTime() { return startTime; }
public void setStartTime(String startTime) { this.startTime = startTime; }
public String getEndTime() { return endTime; }
public void setEndTime(String endTime) { this.endTime = endTime; }
public Integer getSubmitDeadlineDays() { return submitDeadlineDays; }
public void setSubmitDeadlineDays(Integer submitDeadlineDays) { this.submitDeadlineDays = submitDeadlineDays; }
public String getSupportContractUrl() { return supportContractUrl; }
public void setSupportContractUrl(String supportContractUrl) { this.supportContractUrl = supportContractUrl; }
public String getExecuteContractUrl() { return executeContractUrl; }
public void setExecuteContractUrl(String executeContractUrl) { this.executeContractUrl = executeContractUrl; }
public String getInvitationUrl() { return invitationUrl; }
public void setInvitationUrl(String invitationUrl) { this.invitationUrl = invitationUrl; }
public String getSupportLetterUrl() { return supportLetterUrl; }
public void setSupportLetterUrl(String supportLetterUrl) { this.supportLetterUrl = supportLetterUrl; }
public String getPublishUrl() { return publishUrl; }
public void setPublishUrl(String publishUrl) { this.publishUrl = publishUrl; }
public String getNoticeUrl() { return noticeUrl; }
public void setNoticeUrl(String noticeUrl) { this.noticeUrl = noticeUrl; }
public String getScheduleUrl() { return scheduleUrl; }
public void setScheduleUrl(String scheduleUrl) { this.scheduleUrl = scheduleUrl; }
public String getIsPublished() { return isPublished; }
public void setIsPublished(String isPublished) { this.isPublished = isPublished; }
public Date getPublishTime() { return publishTime; }
public void setPublishTime(Date publishTime) { this.publishTime = publishTime; }
public String getAnnouncementType() { return announcementType; }
public void setAnnouncementType(String announcementType) { this.announcementType = announcementType; }
public BigDecimal getSponsorRating() { return sponsorRating; }
public void setSponsorRating(BigDecimal sponsorRating) { this.sponsorRating = sponsorRating; }
public Integer getSponsorQ1() { return sponsorQ1; }
public void setSponsorQ1(Integer sponsorQ1) { this.sponsorQ1 = sponsorQ1; }
public Integer getSponsorQ2() { return sponsorQ2; }
public void setSponsorQ2(Integer sponsorQ2) { this.sponsorQ2 = sponsorQ2; }
public Integer getSponsorQ3() { return sponsorQ3; }
public void setSponsorQ3(Integer sponsorQ3) { this.sponsorQ3 = sponsorQ3; }
public Integer getSponsorQ4() { return sponsorQ4; }
public void setSponsorQ4(Integer sponsorQ4) { this.sponsorQ4 = sponsorQ4; }
public String getSponsorRemark() { return sponsorRemark; }
public void setSponsorRemark(String sponsorRemark) { this.sponsorRemark = sponsorRemark; }
}
@@ -0,0 +1,50 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import com.ruoyi.common.core.domain.BaseEntity;
/** 项目执行方分配对象 BizProjectAssign */
public class BizProjectAssign extends BaseEntity {
private static final long serialVersionUID = 1L;
/** assign_id */
private String assignId;
/** project_id */
private Long projectId;
/** 执行方用户ID (sys_user.user_id) */
private Long execUserId;
/** 执行方用户名 (denormalized) */
private String execUserName;
/** 执行方昵称 (denormalized) */
private String execNickName;
/** 执行方所属机构 (denormalized) */
private String execOrg;
/** 分配场次 */
private Integer sessions;
/** 分配金额 */
private BigDecimal amount;
/** 备注 */
private String remark;
/** 状态 0正常 1已撤销 */
private String status;
public String getAssignId() { return assignId; }
public void setAssignId(String assignId) { this.assignId = assignId; }
public Long getProjectId() { return projectId; }
public void setProjectId(Long projectId) { this.projectId = projectId; }
public Long getExecUserId() { return execUserId; }
public void setExecUserId(Long execUserId) { this.execUserId = execUserId; }
public String getExecUserName() { return execUserName; }
public void setExecUserName(String execUserName) { this.execUserName = execUserName; }
public String getExecNickName() { return execNickName; }
public void setExecNickName(String execNickName) { this.execNickName = execNickName; }
public String getExecOrg() { return execOrg; }
public void setExecOrg(String execOrg) { this.execOrg = execOrg; }
public Integer getSessions() { return sessions; }
public void setSessions(Integer sessions) { this.sessions = sessions; }
public BigDecimal getAmount() { return amount; }
public void setAmount(BigDecimal amount) { this.amount = amount; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
}
@@ -0,0 +1,94 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 项目策划方案对象 BizProjectPlan */
public class BizProjectPlan extends BaseEntity {
private static final long serialVersionUID = 1L;
/** planId */
private String planId;
/** plan_name */
@Excel(name = "plan_name")
private String planName;
/** plan_direction */
@Excel(name = "plan_direction")
private String planDirection;
/** plan_category */
@Excel(name = "plan_category")
private String planCategory;
/** project_form */
@Excel(name = "project_form")
private String projectForm;
/** design_file_url */
@Excel(name = "design_file_url")
private String designFileUrl;
/** status */
@Excel(name = "status")
private String status;
/** is_settled */
@Excel(name = "is_settled")
private String isSettled;
/** project_no */
@Excel(name = "project_no")
private String projectNo;
/** remark */
@Excel(name = "remark")
private String remark;
/** is_finished */
@Excel(name = "is_finished")
private String isFinished;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 审核意见 */
private String auditOpinion;
/** 审核人 */
private String auditBy;
/** 审核时间 */
private String auditTime;
public String getPlanId() { return planId; }
public void setPlanId(String planId) { this.planId = planId; }
public String getPlanName() { return planName; }
public void setPlanName(String planName) { this.planName = planName; }
public String getPlanDirection() { return planDirection; }
public void setPlanDirection(String planDirection) { this.planDirection = planDirection; }
public String getPlanCategory() { return planCategory; }
public void setPlanCategory(String planCategory) { this.planCategory = planCategory; }
public String getProjectForm() { return projectForm; }
public void setProjectForm(String projectForm) { this.projectForm = projectForm; }
public String getDesignFileUrl() { return designFileUrl; }
public void setDesignFileUrl(String designFileUrl) { this.designFileUrl = designFileUrl; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getIsSettled() { return isSettled; }
public void setIsSettled(String isSettled) { this.isSettled = isSettled; }
public String getProjectNo() { return projectNo; }
public void setProjectNo(String projectNo) { this.projectNo = projectNo; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public String getIsFinished() { return isFinished; }
public void setIsFinished(String isFinished) { this.isFinished = isFinished; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}
@@ -0,0 +1,100 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 项目评分对象 BizProjectRating */
public class BizProjectRating extends BaseEntity {
private static final long serialVersionUID = 1L;
/** ratingId */
private String ratingId;
/** project_no */
@Excel(name = "project_no")
private String projectNo;
/** project_name */
@Excel(name = "project_name")
private String projectName;
/** rater_name */
@Excel(name = "rater_name")
private String raterName;
/** rater_role */
@Excel(name = "rater_role")
private String raterRole;
/** quality_score */
@Excel(name = "quality_score")
private String qualityScore;
/** response_score */
@Excel(name = "response_score")
private Long responseScore;
/** cooperation_score */
@Excel(name = "cooperation_score")
private Long cooperationScore;
/** compliance_score */
@Excel(name = "compliance_score")
private Long complianceScore;
/** total_score */
@Excel(name = "total_score")
private BigDecimal totalScore;
/** remark */
@Excel(name = "remark")
private String remark;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 项目ID */
private Long projectId;
/** 评分人ID */
private Long raterId;
/** 评分时间 */
private String ratingTime;
public String getRatingId() { return ratingId; }
public void setRatingId(String ratingId) { this.ratingId = ratingId; }
public String getProjectNo() { return projectNo; }
public void setProjectNo(String projectNo) { this.projectNo = projectNo; }
public String getProjectName() { return projectName; }
public void setProjectName(String projectName) { this.projectName = projectName; }
public String getRaterName() { return raterName; }
public void setRaterName(String raterName) { this.raterName = raterName; }
public String getRaterRole() { return raterRole; }
public void setRaterRole(String raterRole) { this.raterRole = raterRole; }
public String getQualityScore() { return qualityScore; }
public void setQualityScore(String qualityScore) { this.qualityScore = qualityScore; }
public Long getResponseScore() { return responseScore; }
public void setResponseScore(Long responseScore) { this.responseScore = responseScore; }
public Long getCooperationScore() { return cooperationScore; }
public void setCooperationScore(Long cooperationScore) { this.cooperationScore = cooperationScore; }
public Long getComplianceScore() { return complianceScore; }
public void setComplianceScore(Long complianceScore) { this.complianceScore = complianceScore; }
public BigDecimal getTotalScore() { return totalScore; }
public void setTotalScore(BigDecimal totalScore) { this.totalScore = totalScore; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
public Long getProjectId() { return projectId; }
public void setProjectId(Long projectId) { this.projectId = projectId; }
public Long getRaterId() { return raterId; }
public void setRaterId(Long raterId) { this.raterId = raterId; }
public String getRatingTime() { return ratingTime; }
public void setRatingTime(String ratingTime) { this.ratingTime = ratingTime; }
}
@@ -0,0 +1,42 @@
package com.ruoyi.business.domain;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseEntity;
/** 项目-赞助方-监察员分配记录 (biz_project_sponsor_assign) */
public class BizProjectSponsorAssign extends BaseEntity {
private static final long serialVersionUID = 1L;
private Long id;
private String projectId;
private Long sponsorUserId;
private Long monitorUserId;
private String assignDesc;
private String assignPoints;
/** 关联展示字段 (非持久化) */
private String sponsorUserName;
private String monitorUserName;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getProjectId() { return projectId; }
public void setProjectId(String projectId) { this.projectId = projectId; }
public Long getSponsorUserId() { return sponsorUserId; }
public void setSponsorUserId(Long sponsorUserId) { this.sponsorUserId = sponsorUserId; }
public Long getMonitorUserId() { return monitorUserId; }
public void setMonitorUserId(Long monitorUserId) { this.monitorUserId = monitorUserId; }
public String getAssignDesc() { return assignDesc; }
public void setAssignDesc(String assignDesc) { this.assignDesc = assignDesc; }
public String getAssignPoints() { return assignPoints; }
public void setAssignPoints(String assignPoints) { this.assignPoints = assignPoints; }
public String getSponsorUserName() { return sponsorUserName; }
public void setSponsorUserName(String sponsorUserName) { this.sponsorUserName = sponsorUserName; }
public String getMonitorUserName() { return monitorUserName; }
public void setMonitorUserName(String monitorUserName) { this.monitorUserName = monitorUserName; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
}
@@ -0,0 +1,61 @@
package com.ruoyi.business.domain;
import java.util.Date;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 项目公告对象 BizPublicity */
public class BizPublicity extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** PK */
private Long id;
/** 项目ID */
@Excel(name = "project_id")
private Long projectId;
/** 项目编号 */
@Excel(name = "project_no")
private String projectNo;
/** 项目名称 */
@Excel(name = "project_name")
private String projectName;
/** 公告类型 (invitation/support/notice/agenda) */
@Excel(name = "announce_type")
private String announceType;
/** 公告标题 */
@Excel(name = "title")
private String title;
/** 公告文件URL */
@Excel(name = "file_url")
private String fileUrl;
/** 备注 */
@Excel(name = "remark")
private String remark;
/** 状态 0保存 1发布 */
@Excel(name = "status")
private String status;
/** 发布时间 */
@Excel(name = "rating_time")
private Date ratingTime;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public Long getProjectId() { return projectId; }
public void setProjectId(Long projectId) { this.projectId = projectId; }
public String getProjectNo() { return projectNo; }
public void setProjectNo(String projectNo) { this.projectNo = projectNo; }
public String getProjectName() { return projectName; }
public void setProjectName(String projectName) { this.projectName = projectName; }
public String getAnnounceType() { return announceType; }
public void setAnnounceType(String announceType) { this.announceType = announceType; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getFileUrl() { return fileUrl; }
public void setFileUrl(String fileUrl) { this.fileUrl = fileUrl; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public Date getRatingTime() { return ratingTime; }
public void setRatingTime(Date ratingTime) { this.ratingTime = ratingTime; }
}
@@ -0,0 +1,69 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 资料对象 BizResource */
public class BizResource extends BaseEntity {
private static final long serialVersionUID = 1L;
/** resourceId */
private String resourceId;
/** name */
@Excel(name = "name")
private String name;
/** category */
@Excel(name = "category")
private String category;
/** file_size */
@Excel(name = "file_size")
private String fileSize;
/** uploader_name */
@Excel(name = "uploader_name")
private String uploaderName;
/** upload_time */
@Excel(name = "upload_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date uploadTime;
/** status */
@Excel(name = "status")
private String status;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
public String getResourceId() { return resourceId; }
public void setResourceId(String resourceId) { this.resourceId = resourceId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getCategory() { return category; }
public void setCategory(String category) { this.category = category; }
public String getFileSize() { return fileSize; }
public void setFileSize(String fileSize) { this.fileSize = fileSize; }
public String getUploaderName() { return uploaderName; }
public void setUploaderName(String uploaderName) { this.uploaderName = uploaderName; }
public Date getUploadTime() { return uploadTime; }
public void setUploadTime(Date uploadTime) { this.uploadTime = uploadTime; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}
@@ -0,0 +1,86 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 投稿对象 BizSubmission */
public class BizSubmission extends BaseEntity {
private static final long serialVersionUID = 1L;
/** subId */
private String subId;
/** title */
@Excel(name = "title")
private String title;
/** direction */
@Excel(name = "direction")
private String direction;
/** project_form */
@Excel(name = "project_form")
private String projectForm;
/** design_file_url */
@Excel(name = "design_file_url")
private String designFileUrl;
/** status */
@Excel(name = "status")
private String status;
/** remark */
@Excel(name = "remark")
private String remark;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 投稿人用户ID */
private Long submitterId;
/** 投稿人姓名 */
private String submitterName;
/** 项目类别 学术会议类/专项科研类/调研征集类/慈善帮扶类/标准制定类/患者援助类/专业培训类 */
private String projectCategory;
/** 审核意见 */
private String auditOpinion;
/** 审核人 */
private String auditBy;
/** 审核时间 */
private String auditTime;
public String getSubId() { return subId; }
public void setSubId(String subId) { this.subId = subId; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getDirection() { return direction; }
public void setDirection(String direction) { this.direction = direction; }
public String getProjectForm() { return projectForm; }
public void setProjectForm(String projectForm) { this.projectForm = projectForm; }
public String getProjectCategory() { return projectCategory; }
public void setProjectCategory(String projectCategory) { this.projectCategory = projectCategory; }
public String getDesignFileUrl() { return designFileUrl; }
public void setDesignFileUrl(String designFileUrl) { this.designFileUrl = designFileUrl; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public Long getSubmitterId() { return submitterId; }
public void setSubmitterId(Long submitterId) { this.submitterId = submitterId; }
public String getSubmitterName() { return submitterName; }
public void setSubmitterName(String submitterName) { this.submitterName = submitterName; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}
@@ -0,0 +1,78 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 支持意向对象 BizSupportIntent */
public class BizSupportIntent extends BaseEntity {
private static final long serialVersionUID = 1L;
/** intentId */
private String intentId;
/** project_no */
@Excel(name = "project_no")
private String projectNo;
/** project_name */
@Excel(name = "project_name")
private String projectName;
/** name */
@Excel(name = "name")
private String name;
/** work_unit */
@Excel(name = "work_unit")
private String workUnit;
/** department */
@Excel(name = "department")
private String department;
/** position */
@Excel(name = "position")
private String position;
/** phone */
@Excel(name = "phone")
private String phone;
/** account_status */
@Excel(name = "account_status")
private String accountStatus;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
public String getIntentId() { return intentId; }
public void setIntentId(String intentId) { this.intentId = intentId; }
public String getProjectNo() { return projectNo; }
public void setProjectNo(String projectNo) { this.projectNo = projectNo; }
public String getProjectName() { return projectName; }
public void setProjectName(String projectName) { this.projectName = projectName; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getWorkUnit() { return workUnit; }
public void setWorkUnit(String workUnit) { this.workUnit = workUnit; }
public String getDepartment() { return department; }
public void setDepartment(String department) { this.department = department; }
public String getPosition() { return position; }
public void setPosition(String position) { this.position = position; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
public String getAccountStatus() { return accountStatus; }
public void setAccountStatus(String accountStatus) { this.accountStatus = accountStatus; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}
@@ -0,0 +1,76 @@
package com.ruoyi.business.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/** 支持函对象 BizSupportLetter */
public class BizSupportLetter extends BaseEntity {
private static final long serialVersionUID = 1L;
/** annId */
private String annId;
/** title */
@Excel(name = "title")
private String title;
/** content */
@Excel(name = "content")
private String content;
/** unit_name */
@Excel(name = "unit_name")
private String unitName;
/** amount */
@Excel(name = "amount")
private BigDecimal amount;
/** issue_date */
@Excel(name = "issue_date")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date issueDate;
/** create_by */
@Excel(name = "create_by")
private String createBy;
/** create_time */
@Excel(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** update_by */
@Excel(name = "update_by")
private String updateBy;
/** update_time */
@Excel(name = "update_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 支持函ID */
private Long letterId;
/** 项目ID */
private Long projectId;
/** 项目编号 */
private String projectNo;
/** 支持函图片URL */
private String fileUrl;
/** 发布时间 */
private String publishTime;
/** 支持次数 */
private Integer supportCount;
public String getAnnId() { return annId; }
public void setAnnId(String annId) { this.annId = annId; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
public String getUnitName() { return unitName; }
public void setUnitName(String unitName) { this.unitName = unitName; }
public BigDecimal getAmount() { return amount; }
public void setAmount(BigDecimal amount) { this.amount = amount; }
public Date getIssueDate() { return issueDate; }
public void setIssueDate(Date issueDate) { this.issueDate = issueDate; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}
@@ -0,0 +1,22 @@
package com.ruoyi.business.dto;
/**
* 短信验证码校验表单
* 参考 hwt-code SmsValidForm: phone + smsCode + uuid
*/
public class SmsValidForm {
private String phone;
private String smsCode;
private String uuid;
/** 是否免校验(预留, 默认 false) */
private boolean free;
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
public String getSmsCode() { return smsCode; }
public void setSmsCode(String smsCode) { this.smsCode = smsCode; }
public String getUuid() { return uuid; }
public void setUuid(String uuid) { this.uuid = uuid; }
public boolean isFree() { return free; }
public void setFree(boolean free) { this.free = free; }
}
@@ -0,0 +1,43 @@
package com.ruoyi.business.enums;
import java.util.HashMap;
import java.util.Map;
/**
* 投稿状态枚举
*
* 数据库存储英文 code (PENDING/APPROVED/REJECTED/DRAFT), 不存中文也不存数字.
* 字典映射集中在这里避免散落. 前端 utils/submissionStatus.js 同步这份字典.
*/
public enum SubmissionStatus
{
PENDING("PENDING", "待审核"),
APPROVED("APPROVED", "审核通过"),
REJECTED("REJECTED", "已退回"),
DRAFT("DRAFT", "待提交");
private final String code;
private final String label;
SubmissionStatus(String code, String label) {
this.code = code;
this.label = label;
}
public String getCode() { return code; }
public String getLabel() { return label; }
private static final Map<String, SubmissionStatus> BY_CODE = new HashMap<>();
static {
for (SubmissionStatus s : values()) BY_CODE.put(s.code, s);
}
public static SubmissionStatus fromCode(String val) {
if (val == null) return null;
return BY_CODE.get(val.trim().toUpperCase());
}
public static boolean isValid(String val) {
return fromCode(val) != null;
}
}
@@ -0,0 +1,22 @@
package com.ruoyi.business.mapper;
import java.util.List;
import com.ruoyi.business.domain.BizDepartment;
public interface BizDepartmentMapper
{
BizDepartment selectByPrimaryKey(Long deptId);
List<BizDepartment> selectList(BizDepartment entity);
/** 全部启用的字典 (给前端下拉用) */
List<BizDepartment> selectActive();
int insert(BizDepartment entity);
int updateByPrimaryKey(BizDepartment entity);
int deleteByPrimaryKey(Long deptId);
int deleteByPrimaryKeys(Long[] deptIds);
}
@@ -0,0 +1,22 @@
package com.ruoyi.business.mapper;
import java.util.List;
import com.ruoyi.business.domain.BizDoctorTitle;
public interface BizDoctorTitleMapper
{
BizDoctorTitle selectByPrimaryKey(Long titleId);
List<BizDoctorTitle> selectList(BizDoctorTitle entity);
/** 全部启用的字典 */
List<BizDoctorTitle> selectActive();
int insert(BizDoctorTitle entity);
int updateByPrimaryKey(BizDoctorTitle entity);
int deleteByPrimaryKey(Long titleId);
int deleteByPrimaryKeys(Long[] titleIds);
}
@@ -0,0 +1,16 @@
package com.ruoyi.business.mapper;
import java.util.List;
import com.ruoyi.business.domain.BizExecutionIntent;
/**
* 执行意向Mapper接口
*/
public interface BizExecutionIntentMapper
{
BizExecutionIntent selectByPrimaryKey(String intentId);
List<BizExecutionIntent> selectList(BizExecutionIntent entity);
int insert(BizExecutionIntent entity);
int updateByPrimaryKey(BizExecutionIntent entity);
int deleteByPrimaryKey(String intentId);
int deleteByPrimaryKeys(String[] intentIds);
}
@@ -0,0 +1,19 @@
package com.ruoyi.business.mapper;
import java.util.List;
import com.ruoyi.business.domain.BizExpert;
/**
* 专家Mapper接口
*/
public interface BizExpertMapper
{
BizExpert selectByPrimaryKey(String expertId);
BizExpert selectByUserId(Long userId);
List<BizExpert> selectList(BizExpert entity);
int insert(BizExpert entity);
int insertWithUserId(BizExpert entity);
int updateByPrimaryKey(BizExpert entity);
int updateByUserId(BizExpert entity);
int deleteByPrimaryKey(String expertId);
int deleteByPrimaryKeys(String[] expertIds);
}
@@ -0,0 +1,11 @@
package com.ruoyi.business.mapper;
import java.util.List;
import com.ruoyi.business.domain.BizInvitation;
public interface BizInvitationMapper {
BizInvitation selectByPrimaryKey(String annId);
List<BizInvitation> selectList(BizInvitation entity);
int insert(BizInvitation entity);
int updateByPrimaryKey(BizInvitation entity);
int deleteByPrimaryKey(String annId);
int deleteByPrimaryKeys(String[] annIds);
}
@@ -0,0 +1,16 @@
package com.ruoyi.business.mapper;
import java.util.List;
import com.ruoyi.business.domain.BizLaborVoucher;
/**
* 劳务凭证Mapper接口
*/
public interface BizLaborVoucherMapper
{
BizLaborVoucher selectByPrimaryKey(String voucherId);
List<BizLaborVoucher> selectList(BizLaborVoucher entity);
int insert(BizLaborVoucher entity);
int updateByPrimaryKey(BizLaborVoucher entity);
int deleteByPrimaryKey(String voucherId);
int deleteByPrimaryKeys(String[] voucherIds);
}
@@ -0,0 +1,16 @@
package com.ruoyi.business.mapper;
import java.util.List;
import com.ruoyi.business.domain.BizMeeting;
/**
* 会议Mapper接口
*/
public interface BizMeetingMapper
{
BizMeeting selectByPrimaryKey(String meetingId);
List<BizMeeting> selectList(BizMeeting entity);
int insert(BizMeeting entity);
int updateByPrimaryKey(BizMeeting entity);
int deleteByPrimaryKey(String meetingId);
int deleteByPrimaryKeys(String[] meetingIds);
}
@@ -0,0 +1,16 @@
package com.ruoyi.business.mapper;
import java.util.List;
import com.ruoyi.business.domain.BizMeetingSettlement;
/**
* 会议结算明细Mapper接口
*/
public interface BizMeetingSettlementMapper
{
BizMeetingSettlement selectByPrimaryKey(String id);
List<BizMeetingSettlement> selectList(BizMeetingSettlement entity);
int insert(BizMeetingSettlement entity);
int updateByPrimaryKey(BizMeetingSettlement entity);
int deleteByPrimaryKey(String id);
int deleteByPrimaryKeys(String[] ids);
}
@@ -0,0 +1,31 @@
package com.ruoyi.business.mapper;
import java.util.List;
import com.ruoyi.business.domain.BizMessage;
/**
* 个人消息Mapper接口
*/
public interface BizMessageMapper
{
BizMessage selectByPrimaryKey(Long msgId);
List<BizMessage> selectList(BizMessage entity);
/** 某人的未读 + 最近消息 (按时间倒序, limit 由调用方控制) */
List<BizMessage> selectMyRecent(BizMessage entity);
int insert(BizMessage entity);
int updateByPrimaryKey(BizMessage entity);
/** 单条标记已读 */
int markRead(BizMessage entity);
/** 全部标记已读 (按接收人) */
int markAllRead(Long receiverUserId);
int deleteByPrimaryKey(Long msgId);
int deleteByPrimaryKeys(Long[] msgIds);
}
@@ -0,0 +1,12 @@
package com.ruoyi.business.mapper;
import java.util.List;
import com.ruoyi.business.domain.BizOrg;
public interface BizOrgMapper {
BizOrg selectByPrimaryKey(Long orgId);
List<BizOrg> selectList(BizOrg entity);
int insert(BizOrg entity);
int updateByPrimaryKey(BizOrg entity);
int deleteByPrimaryKeys(Long[] orgIds);
}
@@ -0,0 +1,20 @@
package com.ruoyi.business.mapper;
import java.util.List;
import com.ruoyi.business.domain.BizPerson;
/**
* 人员Mapper接口
*/
public interface BizPersonMapper
{
BizPerson selectByPrimaryKey(String personId);
List<BizPerson> selectList(BizPerson entity);
/** sponsor 专属: 通过 sys_user.parent_user_id 过滤主账号归属, INNER JOIN 自然排除游离 person */
List<BizPerson> selectSponsorList(BizPerson entity);
int insert(BizPerson entity);
int updateByPrimaryKey(BizPerson entity);
int deleteByPrimaryKey(String personId);
int deleteByPrimaryKeys(String[] personIds);
/** 联动: person 逻辑删除后, 把对应 sys_user 子账号也逻辑删除 */
int softDeleteSysUserByPersonIds(String[] personIds);
}

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