球机模块代码开发

This commit is contained in:
tangcy 2026-01-20 18:01:36 +08:00
parent ddd2868db2
commit 702ac4dba5
10 changed files with 368 additions and 43 deletions

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"java.compile.nullAnalysis.mode": "automatic"
}

View File

@ -0,0 +1,120 @@
# 网关路由配置修复说明
## 问题分析
您的网关配置中已经包含了 `ruoyi-system``ruoyi-manage` 的路由,但是 **缺少 Swagger 文档的专门路由**
### 当前路由配置
- `ruoyi-system``/system/**`
- `ruoyi-manage``/manage/**`
### Swagger 文档访问路径
- `ruoyi-system` Swagger → `/ruoyi-system/v3/api-docs`
- `ruoyi-manage` Swagger → `/ruoyi-manage/v3/api-docs`
**问题**`/ruoyi-system/v3/api-docs` 和 `/ruoyi-manage/v3/api-docs` 无法匹配现有的路由规则!
## 解决方案
在 Nacos 配置中心的 `ruoyi-gateway-dev.yml` 文件中,添加 Swagger 文档的专门路由:
```yaml
spring:
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
routes:
# 认证中心
- id: ruoyi-auth
uri: lb://ruoyi-auth
predicates:
- Path=/auth/**
filters:
- CacheRequestBody
- ValidateCodeFilter
- StripPrefix=1
# 代码生成
- id: ruoyi-gen
uri: lb://ruoyi-gen
predicates:
- Path=/code/**
filters:
- StripPrefix=1
# 定时任务
- id: ruoyi-job
uri: lb://ruoyi-job
predicates:
- Path=/schedule/**
filters:
- StripPrefix=1
# 系统模块
- id: ruoyi-system
uri: lb://ruoyi-system
predicates:
- Path=/system/**
filters:
- StripPrefix=1
# 系统模块 Swagger 文档(新增)
- id: ruoyi-system-swagger
uri: lb://ruoyi-system
predicates:
- Path=/ruoyi-system/v3/api-docs/**
filters:
- StripPrefix=1
# 文件服务
- id: ruoyi-file
uri: lb://ruoyi-file
predicates:
- Path=/file/**
filters:
- StripPrefix=1
# 物业施工作业管理系统
- id: ruoyi-manage
uri: lb://ruoyi-manage
predicates:
- Path=/manage/**
filters:
- StripPrefix=1
# 物业施工作业管理系统 Swagger 文档(新增)
- id: ruoyi-manage-swagger
uri: lb://ruoyi-manage
predicates:
- Path=/ruoyi-manage/v3/api-docs/**
filters:
- StripPrefix=1
```
## 操作步骤
1. 登录 Nacos 控制台:`http://127.0.0.1:8848/nacos`
2. 进入"配置管理" -> "配置列表"
3. 找到 `ruoyi-gateway-dev.yml` 配置文件
4. 在 `routes` 列表中添加上述两个 Swagger 路由配置
5. 点击"发布"保存配置
6. **重启网关服务**`ruoyi-gateway`
## 验证
配置完成后,访问以下 URL 验证:
1. **Swagger 文档**
- `http://localhost:8080/ruoyi-system/v3/api-docs` - 应该返回系统模块的 API 文档 JSON
- `http://localhost:8080/ruoyi-manage/v3/api-docs` - 应该返回管理模块的 API 文档 JSON
2. **Swagger UI**
- `http://localhost:8080/swagger-ui.html``http://localhost:8080/doc.html`
- 在服务下拉列表中应该能看到 `ruoyi-system``ruoyi-manage`
- 选择服务后应该能看到"用户管理"和"部门管理"的接口
3. **业务接口**
- `http://localhost:8080/system/user/list` - 用户列表
- `http://localhost:8080/system/dept/list` - 部门列表
## 注意事项
- 路由配置修改后必须重启网关服务才能生效
- `StripPrefix=1` 表示去掉路径的第一段(如 `/ruoyi-system/v3/api-docs` 会变成 `/v3/api-docs` 转发到后端服务)
- Swagger 文档路径已经在白名单中(`/*/v3/api-docs`),不需要认证即可访问

View File

@ -0,0 +1,95 @@
# 网关路由配置说明
## 问题分析
用户管理和部门管理的 Swagger 接口不显示,可能是因为网关路由配置缺失。
## 网关路由配置位置
网关路由配置在 **Nacos 配置中心**,配置文件名:`application-dev.yml`(根据环境可能是 `application-prod.yml` 等)
## 需要检查的配置
### 1. 登录 Nacos 控制台
- 地址:`http://127.0.0.1:8848/nacos`
- 用户名/密码:`nacos/nacos`(默认)
### 2. 查找配置文件
- **Data ID**: `application-dev.yml`
- **Group**: `DEFAULT_GROUP`
- **命名空间**: 根据实际情况选择
### 3. 检查路由配置
网关路由配置应该包含以下内容:
```yaml
spring:
cloud:
gateway:
discovery:
locator:
enabled: true # 启用服务发现自动路由
lower-case-service-id: true # 服务ID转小写
routes:
# ruoyi-system 路由配置
- id: ruoyi-system
uri: lb://ruoyi-system
predicates:
- Path=/system/**
filters:
- StripPrefix=1
# ruoyi-manage 路由配置
- id: ruoyi-manage
uri: lb://ruoyi-manage
predicates:
- Path=/manage/**
filters:
- StripPrefix=1
# Swagger 路由配置
- id: ruoyi-system-swagger
uri: lb://ruoyi-system
predicates:
- Path=/ruoyi-system/v3/api-docs/**
filters:
- StripPrefix=1
- id: ruoyi-manage-swagger
uri: lb://ruoyi-manage
predicates:
- Path=/ruoyi-manage/v3/api-docs/**
filters:
- StripPrefix=1
```
## 如果配置不存在
如果 Nacos 中没有上述路由配置,需要添加:
1. 登录 Nacos 控制台
2. 进入"配置管理" -> "配置列表"
3. 找到或创建 `application-dev.yml`
4. 添加上述路由配置
5. 发布配置
6. 重启网关服务
## 验证步骤
1. **检查服务注册**:在 Nacos 控制台的"服务管理" -> "服务列表"中,确认以下服务已注册:
- `ruoyi-system`
- `ruoyi-manage`
2. **检查路由**:访问以下 URL 验证路由是否正常:
- `http://localhost:8080/system/user/list` - 系统模块用户列表
- `http://localhost:8080/manage/unit/archive/list` - 管理模块单位建档列表
- `http://localhost:8080/ruoyi-system/v3/api-docs` - 系统模块 Swagger 文档
- `http://localhost:8080/ruoyi-manage/v3/api-docs` - 管理模块 Swagger 文档
3. **检查 Swagger UI**
- 访问:`http://localhost:8080/swagger-ui.html` 或 `http://localhost:8080/doc.html`
- 在服务下拉列表中应该能看到 `ruoyi-system``ruoyi-manage`
## 注意事项
- 如果启用了 `discovery.locator.enabled: true`,网关会自动为所有注册的服务创建路由,路径格式为:`/服务名/**`
- 但为了更好的控制和明确的路由规则,建议显式配置路由
- 路由配置修改后需要重启网关服务才能生效

View File

@ -27,7 +27,7 @@ public class PcCameraReturnController extends BaseController {
this.bizService = bizService; this.bizService = bizService;
} }
@Operation(summary = "回收记录列表(已回收待入库/已入库/已驳回等") @Operation(summary = "待回收列表(已分配但未提交回收的球机")
@PreAuthorize("@ss.hasPermi('property:camera:return:list')") @PreAuthorize("@ss.hasPermi('property:camera:return:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(PcCameraReturn query) { public TableDataInfo list(PcCameraReturn query) {

View File

@ -12,12 +12,24 @@ import java.util.Date;
@Schema(description = "球机入库记录") @Schema(description = "球机入库记录")
public class PcCameraInbound extends BaseEntity { public class PcCameraInbound extends BaseEntity {
@Schema(description = "入库ID")
private Long inboundId; private Long inboundId;
@Schema(description = "回收记录ID")
private Long returnId; private Long returnId;
@Schema(description = "球机ID")
private Long cameraId; private Long cameraId;
@Schema(description = "仓库")
private String warehouse; private String warehouse;
@Schema(description = "库管/审核人")
private String keeper; private String keeper;
@Schema(description = "入库时间")
private Date inboundTime; private Date inboundTime;
@Schema(description = "备注")
private String remark; private String remark;
} }

View File

@ -12,35 +12,67 @@ import java.util.Date;
@Schema(description = "球机回收记录(待入库审核)") @Schema(description = "球机回收记录(待入库审核)")
public class PcCameraReturn extends BaseEntity { public class PcCameraReturn extends BaseEntity {
@Schema(description = "回收记录ID")
private Long returnId; private Long returnId;
@Schema(description = "分配记录ID")
private Long allocId; private Long allocId;
@Schema(description = "项目ID")
private Long projectId; private Long projectId;
@Schema(description = "球机ID")
private Long cameraId; private Long cameraId;
@Schema(description = "0合格 1不合格 2不齐全") @Schema(description = "外观完整性0完好 1破损 2丢失")
private String checkResult; private String appearanceIntegrity;
@Schema(description = "功能测试结果0正常 1异常")
private String functionalTestResult;
@Schema(description = "回收人")
private String returnBy; private String returnBy;
@Schema(description = "回收时间")
private Date returnTime; private Date returnTime;
@Schema(description = "回收照片url逗号分隔") @Schema(description = "回收照片url逗号分隔")
private String photoUrls; private String photoUrls;
@Schema(description = "备注")
private String remark; private String remark;
@Schema(description = "0待审核 1已通过 2已驳回") @Schema(description = "回收状态:-1待回收 0待审核 1已通过 2已驳回")
private String auditStatus; private String auditStatus;
@Schema(description = "审核人")
private String auditBy; private String auditBy;
@Schema(description = "审核时间")
private Date auditTime; private Date auditTime;
@Schema(description = "审核备注")
private String auditRemark; private String auditRemark;
@Schema(description = "删除标志0代表存在 2代表删除")
private String delFlag; private String delFlag;
// JOIN展示字段 // JOIN展示字段
@Schema(description = "球机编号(关联查询)")
private String cameraNo; private String cameraNo;
@Schema(description = "球机ID列表聚合逗号分隔用于待回收列表")
private String cameraIds;
@Schema(description = "球机型号(关联查询)")
private String model; private String model;
@Schema(description = "项目名称(关联查询)")
private String projectName; private String projectName;
@Schema(description = "施工单位(关联查询)")
private String constructionUnit; private String constructionUnit;
@Schema(description = "作业地点(关联查询)")
private String workLocation; private String workLocation;
} }

View File

@ -19,6 +19,9 @@ public class PcCameraAllocConfirmDTO {
@Schema(description = "分配时间(不传则取当前时间)") @Schema(description = "分配时间(不传则取当前时间)")
private Date allocTime; private Date allocTime;
@Schema(description = "分配人(不传则取当前登录用户)")
private String allocBy;
@Schema(description = "分配备注") @Schema(description = "分配备注")
private String allocNote; private String allocNote;
} }

View File

@ -16,8 +16,11 @@ public class PcCameraReturnSubmitDTO {
@Schema(description = "回收球机ID列表") @Schema(description = "回收球机ID列表")
private List<Long> cameraIds; private List<Long> cameraIds;
@Schema(description = "0合格 1不合格 2不齐全") @Schema(description = "外观完整性0完好 1破损 2丢失")
private String checkResult; private String appearanceIntegrity;
@Schema(description = "功能测试结果0正常 1异常")
private String functionalTestResult;
@Schema(description = "回收时间(不传则取当前时间)") @Schema(description = "回收时间(不传则取当前时间)")
private Date returnTime; private Date returnTime;

View File

@ -59,6 +59,7 @@ public class PcCameraBizServiceImpl implements IPcCameraBizService {
if (project == null) throw new ServiceException("项目不存在或已删除"); if (project == null) throw new ServiceException("项目不存在或已删除");
Date allocTime = dto.getAllocTime() != null ? dto.getAllocTime() : new Date(); Date allocTime = dto.getAllocTime() != null ? dto.getAllocTime() : new Date();
String allocBy = dto.getAllocBy() != null && !dto.getAllocBy().isEmpty() ? dto.getAllocBy() : SecurityUtils.getUsername();
String username = SecurityUtils.getUsername(); String username = SecurityUtils.getUsername();
// 校验球机是否可分配 + 状态更新在库->已分配 // 校验球机是否可分配 + 状态更新在库->已分配
@ -92,7 +93,7 @@ public class PcCameraBizServiceImpl implements IPcCameraBizService {
a.setProjectId(dto.getProjectId()); a.setProjectId(dto.getProjectId());
a.setCameraId(cameraId); a.setCameraId(cameraId);
a.setAllocTime(allocTime); a.setAllocTime(allocTime);
a.setAllocBy(username); a.setAllocBy(allocBy);
a.setAllocNote(dto.getAllocNote()); a.setAllocNote(dto.getAllocNote());
a.setAllocStatus(PcAllocStatus.ALLOCATED); a.setAllocStatus(PcAllocStatus.ALLOCATED);
a.setCreateBy(username); a.setCreateBy(username);
@ -128,7 +129,8 @@ public class PcCameraBizServiceImpl implements IPcCameraBizService {
public int submitReturn(PcCameraReturnSubmitDTO dto) { public int submitReturn(PcCameraReturnSubmitDTO dto) {
if (dto.getProjectId() == null) throw new ServiceException("projectId不能为空"); if (dto.getProjectId() == null) throw new ServiceException("projectId不能为空");
if (dto.getCameraIds() == null || dto.getCameraIds().isEmpty()) throw new ServiceException("cameraIds不能为空"); if (dto.getCameraIds() == null || dto.getCameraIds().isEmpty()) throw new ServiceException("cameraIds不能为空");
if (dto.getCheckResult() == null || dto.getCheckResult().isEmpty()) throw new ServiceException("checkResult不能为空"); if (dto.getAppearanceIntegrity() == null || dto.getAppearanceIntegrity().isEmpty()) throw new ServiceException("appearanceIntegrity不能为空");
if (dto.getFunctionalTestResult() == null || dto.getFunctionalTestResult().isEmpty()) throw new ServiceException("functionalTestResult不能为空");
String username = SecurityUtils.getUsername(); String username = SecurityUtils.getUsername();
Date returnTime = dto.getReturnTime() != null ? dto.getReturnTime() : new Date(); Date returnTime = dto.getReturnTime() != null ? dto.getReturnTime() : new Date();
@ -170,7 +172,8 @@ public class PcCameraBizServiceImpl implements IPcCameraBizService {
r.setAllocId(a.getAllocId()); r.setAllocId(a.getAllocId());
r.setProjectId(dto.getProjectId()); r.setProjectId(dto.getProjectId());
r.setCameraId(cameraId); r.setCameraId(cameraId);
r.setCheckResult(dto.getCheckResult()); r.setAppearanceIntegrity(dto.getAppearanceIntegrity());
r.setFunctionalTestResult(dto.getFunctionalTestResult());
r.setReturnBy(username); r.setReturnBy(username);
r.setReturnTime(returnTime); r.setReturnTime(returnTime);
r.setPhotoUrls(photoUrls); r.setPhotoUrls(photoUrls);
@ -232,11 +235,15 @@ public class PcCameraBizServiceImpl implements IPcCameraBizService {
inboundList.add(in); inboundList.add(in);
// 可选同步台账的仓库字段 // 可选同步台账的仓库字段
PcCameraLedger ledger = new PcCameraLedger(); PcCameraLedger existingLedger = ledgerMapper.selectPcCameraLedgerByCameraId(r.getCameraId());
ledger.setCameraId(r.getCameraId()); if (existingLedger != null) {
ledger.setWarehouse(dto.getWarehouse()); PcCameraLedger ledger = new PcCameraLedger();
ledger.setUpdateBy(username); ledger.setCameraId(r.getCameraId());
ledgerMapper.updatePcCameraLedger(ledger); ledger.setCameraNo(existingLedger.getCameraNo()); // camera_no 字段必填
ledger.setWarehouse(dto.getWarehouse());
ledger.setUpdateBy(username);
ledgerMapper.updatePcCameraLedger(ledger);
}
} }
inboundMapper.insertBatch(inboundList); inboundMapper.insertBatch(inboundList);

View File

@ -5,38 +5,54 @@
<mapper namespace="com.admin.property.mapper.PcCameraReturnMapper"> <mapper namespace="com.admin.property.mapper.PcCameraReturnMapper">
<select id="selectReturnList" resultType="com.admin.property.domain.PcCameraReturn"> <select id="selectReturnList" resultType="com.admin.property.domain.PcCameraReturn">
select r.return_id as returnId, -- 待回收列表:从分配表查询(已分配但未提交回收),按项目分组聚合
r.alloc_id as allocId, select
r.project_id as projectId, null as returnId,
r.camera_id as cameraId, null as allocId,
r.check_result as checkResult, a.project_id as projectId,
r.return_by as returnBy, null as cameraId,
r.return_time as returnTime, null as appearanceIntegrity,
r.photo_urls as photoUrls, null as functionalTestResult,
r.remark as remark, null as returnBy,
r.audit_status as auditStatus, MAX(a.alloc_time) as returnTime,
r.audit_by as auditBy, null as photoUrls,
r.audit_time as auditTime, null as remark,
r.audit_remark as auditRemark, '-1' as auditStatus,
l.camera_no as cameraNo, null as auditBy,
l.model as model, null as auditTime,
null as auditRemark,
GROUP_CONCAT(l.camera_no ORDER BY l.camera_no SEPARATOR ', ') as cameraNo,
GROUP_CONCAT(CAST(a.camera_id AS CHAR) ORDER BY a.camera_id SEPARATOR ', ') as cameraIds,
null as model,
p.project_name as projectName, p.project_name as projectName,
p.construction_unit as constructionUnit, p.construction_unit as constructionUnit,
p.work_location as workLocation p.work_location as workLocation
from pc_camera_return r from pc_camera_alloc a
left join pc_camera_ledger l on l.camera_id=r.camera_id and l.del_flag='0' left join pc_camera_ledger l on l.camera_id = a.camera_id and l.del_flag='0'
left join pc_risk_project p on p.project_id=r.project_id and p.del_flag='0' left join pc_risk_project p on p.project_id = a.project_id and p.del_flag='0'
where r.del_flag='0' where a.del_flag='0'
and a.alloc_status='1'
and l.status='1'
-- 排除已提交回收的记录(通过 NOT EXISTS 判断 return 表中是否存在)
and not exists (
select 1 from pc_camera_return r2
where r2.alloc_id = a.alloc_id
and r2.del_flag='0'
)
<if test="projectName != null and projectName != ''"> <if test="projectName != null and projectName != ''">
and p.project_name like concat('%', #{projectName}, '%') and p.project_name like concat('%', #{projectName}, '%')
</if> </if>
<if test="cameraNo != null and cameraNo != ''"> <if test="cameraNo != null and cameraNo != ''">
and l.camera_no like concat('%', #{cameraNo}, '%') and l.camera_no like concat('%', #{cameraNo}, '%')
</if> </if>
<if test="auditStatus != null and auditStatus != ''"> <if test="constructionUnit != null and constructionUnit != ''">
and r.audit_status = #{auditStatus} and p.construction_unit like concat('%', #{constructionUnit}, '%')
</if> </if>
order by r.return_id desc <if test="workLocation != null and workLocation != ''">
and p.work_location like concat('%', #{workLocation}, '%')
</if>
group by a.project_id, p.project_name, p.construction_unit, p.work_location
order by MAX(a.alloc_time) desc, a.project_id desc
</select> </select>
<select id="selectAuditPendingList" resultType="com.admin.property.domain.PcCameraReturn"> <select id="selectAuditPendingList" resultType="com.admin.property.domain.PcCameraReturn">
@ -44,7 +60,8 @@
r.alloc_id as allocId, r.alloc_id as allocId,
r.project_id as projectId, r.project_id as projectId,
r.camera_id as cameraId, r.camera_id as cameraId,
r.check_result as checkResult, r.appearance_integrity as appearanceIntegrity,
r.functional_test_result as functionalTestResult,
r.return_by as returnBy, r.return_by as returnBy,
r.return_time as returnTime, r.return_time as returnTime,
r.photo_urls as photoUrls, r.photo_urls as photoUrls,
@ -70,23 +87,56 @@
<insert id="insertBatch"> <insert id="insertBatch">
insert into pc_camera_return( insert into pc_camera_return(
alloc_id, project_id, camera_id, check_result, return_by, return_time, photo_urls, remark, alloc_id, project_id, camera_id, appearance_integrity, functional_test_result, return_by, return_time, photo_urls, remark,
audit_status, del_flag, create_by, create_time, update_by, update_time audit_status, del_flag, create_by, create_time, update_by, update_time
) values ) values
<foreach collection="list" item="it" separator=","> <foreach collection="list" item="it" separator=",">
(#{it.allocId}, #{it.projectId}, #{it.cameraId}, #{it.checkResult}, #{it.returnBy}, #{it.returnTime}, (#{it.allocId}, #{it.projectId}, #{it.cameraId}, #{it.appearanceIntegrity}, #{it.functionalTestResult}, #{it.returnBy}, #{it.returnTime},
#{it.photoUrls}, #{it.remark}, #{it.auditStatus}, '0', #{it.createBy}, now(), #{it.updateBy}, now()) #{it.photoUrls}, #{it.remark}, #{it.auditStatus}, '0', #{it.createBy}, now(), #{it.updateBy}, now())
</foreach> </foreach>
</insert> </insert>
<select id="selectById" resultType="com.admin.property.domain.PcCameraReturn"> <select id="selectById" resultType="com.admin.property.domain.PcCameraReturn">
select * from pc_camera_return where return_id=#{returnId} and del_flag='0' select
r.return_id as returnId,
r.alloc_id as allocId,
r.project_id as projectId,
r.camera_id as cameraId,
r.appearance_integrity as appearanceIntegrity,
r.functional_test_result as functionalTestResult,
r.return_by as returnBy,
r.return_time as returnTime,
r.photo_urls as photoUrls,
r.remark as remark,
r.audit_status as auditStatus,
r.audit_by as auditBy,
r.audit_time as auditTime,
r.audit_remark as auditRemark,
r.del_flag as delFlag
from pc_camera_return r
where r.return_id=#{returnId} and r.del_flag='0'
</select> </select>
<select id="selectByIds" resultType="com.admin.property.domain.PcCameraReturn"> <select id="selectByIds" resultType="com.admin.property.domain.PcCameraReturn">
select * from pc_camera_return select
where del_flag='0' r.return_id as returnId,
and return_id in r.alloc_id as allocId,
r.project_id as projectId,
r.camera_id as cameraId,
r.appearance_integrity as appearanceIntegrity,
r.functional_test_result as functionalTestResult,
r.return_by as returnBy,
r.return_time as returnTime,
r.photo_urls as photoUrls,
r.remark as remark,
r.audit_status as auditStatus,
r.audit_by as auditBy,
r.audit_time as auditTime,
r.audit_remark as auditRemark,
r.del_flag as delFlag
from pc_camera_return r
where r.del_flag='0'
and r.return_id in
<foreach collection="returnIds" item="id" open="(" close=")" separator=","> <foreach collection="returnIds" item="id" open="(" close=")" separator=",">
#{id} #{id}
</foreach> </foreach>