feat(tenant): 租户-项目两级架构 Phase 2 — IoT + Ops 业务迁移

DO 迁移 (15个 TenantBaseDO → ProjectBaseDO):
- IoT: IotDeviceDO
- Ops 核心: OpsOrderDO, OpsOrderEventDO, OpsOrderDispatchDO, OpsOrderQueueDO,
  OpsBusAreaDO, OpsAreaDeviceRelationDO, OpsDeviceTrajectoryDO
- Ops 保洁: OpsOrderCleanExtDO, OpsCleanerStatusDO, OpsCleanerPerformanceMonthlyDO,
  OpsInspectionRecordDO, OpsInspectionRecordItemDO
- Ops 安保: OpsOrderSecurityExtDO, OpsAreaSecurityUserDO

IoT 适配:
- IotDeviceRespDTO 新增 projectId 字段
- IotDeviceMessage 新增 projectId 字段
- IotDeviceMessageServiceImpl.appendDeviceMessage() 设置 projectId
- IotCleanRuleMessageHandler 嵌套 ProjectUtils.execute() 设置项目上下文

缓存改造:
- ProjectRedisCacheManager extends TenantRedisCacheManager,追加 :projectId 后缀
- ViewshTenantAutoConfiguration 替换为 ProjectRedisCacheManager

SQL 迁移脚本 (sql/mysql/project/):
- 01-create-tables.sql: system_project + system_user_project 建表
- 02-default-data.sql: 默认项目 + 用户关联回填
- 03-alter-business-tables.sql: 15 张表添加 project_id (NULL → 回填 → NOT NULL → 索引)
- 04-index-audit.sql: 现有索引审计 + project_id 补充建议
- 99-rollback.sql: 完整回滚方案

附带修复:
- fix(ops): UserDispatchStatusServiceImpl 添加缺失的 KEY_PREFIX 常量

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
lzh
2026-04-16 22:27:34 +08:00
parent 87beb1228e
commit a2f500fa20
27 changed files with 648 additions and 176 deletions

View File

@@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.viewsh.framework.tenant.core.db.TenantBaseDO;
import com.viewsh.framework.tenant.core.db.ProjectBaseDO;
import lombok.*;
import java.util.Map;
@@ -27,7 +27,7 @@ import java.util.Map;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OpsAreaDeviceRelationDO extends TenantBaseDO {
public class OpsAreaDeviceRelationDO extends ProjectBaseDO {
/**
* 主键

View File

@@ -1,6 +1,6 @@
package com.viewsh.module.ops.dal.dataobject.area;
import com.viewsh.framework.tenant.core.db.TenantBaseDO;
import com.viewsh.framework.tenant.core.db.ProjectBaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -19,7 +19,7 @@ import lombok.*;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OpsBusAreaDO extends TenantBaseDO {
public class OpsBusAreaDO extends ProjectBaseDO {
/**
* 区域ID主键

View File

@@ -4,7 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.viewsh.framework.tenant.core.db.TenantBaseDO;
import com.viewsh.framework.tenant.core.db.ProjectBaseDO;
import com.viewsh.module.ops.enums.OrderQueueStatusEnum;
import com.viewsh.module.ops.enums.PriorityEnum;
import lombok.*;
@@ -24,7 +24,7 @@ import java.time.LocalDateTime;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OpsOrderQueueDO extends TenantBaseDO {
public class OpsOrderQueueDO extends ProjectBaseDO {
/**
* 队列ID主键

View File

@@ -3,7 +3,7 @@ package com.viewsh.module.ops.dal.dataobject.trajectory;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.viewsh.framework.tenant.core.db.TenantBaseDO;
import com.viewsh.framework.tenant.core.db.ProjectBaseDO;
import lombok.*;
import java.time.LocalDateTime;
@@ -24,7 +24,7 @@ import java.time.LocalDateTime;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OpsDeviceTrajectoryDO extends TenantBaseDO {
public class OpsDeviceTrajectoryDO extends ProjectBaseDO {
/**
* 主键

View File

@@ -1,6 +1,6 @@
package com.viewsh.module.ops.dal.dataobject.workorder;
import com.viewsh.framework.tenant.core.db.TenantBaseDO;
import com.viewsh.framework.tenant.core.db.ProjectBaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -21,7 +21,7 @@ import java.time.LocalDateTime;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OpsOrderDO extends TenantBaseDO {
public class OpsOrderDO extends ProjectBaseDO {
/**
* 工单ID

View File

@@ -1,7 +1,7 @@
package com.viewsh.module.ops.dal.dataobject.workorder;
import com.baomidou.mybatisplus.annotation.TableField;
import com.viewsh.framework.tenant.core.db.TenantBaseDO;
import com.viewsh.framework.tenant.core.db.ProjectBaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -24,7 +24,7 @@ import java.util.Map;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OpsOrderDispatchDO extends TenantBaseDO {
public class OpsOrderDispatchDO extends ProjectBaseDO {
/**
* 派单ID

View File

@@ -1,7 +1,7 @@
package com.viewsh.module.ops.dal.dataobject.workorder;
import com.baomidou.mybatisplus.annotation.IdType;
import com.viewsh.framework.tenant.core.db.TenantBaseDO;
import com.viewsh.framework.tenant.core.db.ProjectBaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@@ -20,7 +20,7 @@ import java.time.LocalDateTime;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OpsOrderEventDO extends TenantBaseDO {
public class OpsOrderEventDO extends ProjectBaseDO {
/**
* 事件ID使用<E4BDBF><E794A8>花算法生成

View File

@@ -31,6 +31,7 @@ import java.util.stream.Collectors;
public class UserDispatchStatusServiceImpl implements UserDispatchStatusService {
private static final long TTL_SECONDS = 24 * 3600; // 24h
private static final String KEY_PREFIX = "ops:user:dispatch:";
@Resource
private StringRedisTemplate stringRedisTemplate;