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:
38
sql/mysql/project/01-create-tables.sql
Normal file
38
sql/mysql/project/01-create-tables.sql
Normal file
@@ -0,0 +1,38 @@
|
||||
-- =============================================
|
||||
-- 租户-项目两级架构 - 建表脚本
|
||||
-- =============================================
|
||||
|
||||
-- 1. 项目表
|
||||
CREATE TABLE IF NOT EXISTS system_project (
|
||||
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '项目编号',
|
||||
tenant_id BIGINT NOT NULL COMMENT '所属租户编号',
|
||||
name VARCHAR(100) NOT NULL COMMENT '项目名称',
|
||||
code VARCHAR(50) NOT NULL COMMENT '项目编码(如楼盘编号)',
|
||||
status TINYINT DEFAULT 0 COMMENT '状态(0=正常, 1=禁用)',
|
||||
contact_name VARCHAR(30) COMMENT '项目联系人',
|
||||
contact_mobile VARCHAR(30) COMMENT '联系手机',
|
||||
address VARCHAR(500) COMMENT '项目地址',
|
||||
remark VARCHAR(500) COMMENT '备注',
|
||||
creator VARCHAR(64) DEFAULT '' COMMENT '创建者',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
updater VARCHAR(64) DEFAULT '' COMMENT '更新者',
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
deleted BIT DEFAULT 0 COMMENT '是否删除',
|
||||
UNIQUE KEY uk_tenant_code (tenant_id, code, deleted),
|
||||
INDEX idx_tenant (tenant_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='项目表';
|
||||
|
||||
-- 2. 用户-项目关联表
|
||||
CREATE TABLE IF NOT EXISTS system_user_project (
|
||||
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '编号',
|
||||
user_id BIGINT NOT NULL COMMENT '用户编号',
|
||||
project_id BIGINT NOT NULL COMMENT '项目编号',
|
||||
tenant_id BIGINT NOT NULL COMMENT '租户编号',
|
||||
creator VARCHAR(64) DEFAULT '' COMMENT '创建者',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
updater VARCHAR(64) DEFAULT '' COMMENT '更新者',
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
deleted BIT DEFAULT 0 COMMENT '是否删除',
|
||||
UNIQUE KEY uk_user_project (user_id, project_id, deleted),
|
||||
INDEX idx_project (project_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户-项目关联表';
|
||||
21
sql/mysql/project/02-default-data.sql
Normal file
21
sql/mysql/project/02-default-data.sql
Normal file
@@ -0,0 +1,21 @@
|
||||
-- =============================================
|
||||
-- 租户-项目两级架构 - 默认数据迁移
|
||||
-- 为每个现有租户创建默认项目,为所有用户关联默认项目
|
||||
-- =============================================
|
||||
|
||||
-- Step 1: 为每个现有租户创建默认项目
|
||||
INSERT INTO system_project (tenant_id, name, code, status, remark, creator, updater, deleted)
|
||||
SELECT id, name, 'DEFAULT', 0, '系统自动生成默认项目', 'system', 'system', 0
|
||||
FROM system_tenant WHERE deleted = 0;
|
||||
|
||||
-- Step 2: 为所有用户关联默认项目
|
||||
INSERT INTO system_user_project (user_id, project_id, tenant_id, creator, updater, deleted)
|
||||
SELECT u.id, p.id, u.tenant_id, 'system', 'system', 0
|
||||
FROM system_users u
|
||||
JOIN system_project p ON p.tenant_id = u.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
WHERE u.deleted = 0;
|
||||
|
||||
-- 验证
|
||||
SELECT '默认项目数量' AS metric, COUNT(*) AS value FROM system_project WHERE code = 'DEFAULT' AND deleted = 0
|
||||
UNION ALL
|
||||
SELECT '用户-项目关联数量', COUNT(*) FROM system_user_project WHERE deleted = 0;
|
||||
215
sql/mysql/project/03-alter-business-tables.sql
Normal file
215
sql/mysql/project/03-alter-business-tables.sql
Normal file
@@ -0,0 +1,215 @@
|
||||
-- =============================================
|
||||
-- 租户-项目两级架构 - 业务表增加 project_id 字段
|
||||
-- 执行顺序:ADD NULL → UPDATE 回填 → MODIFY NOT NULL → ADD INDEX
|
||||
-- 前置条件:02-default-data.sql 已执行,system_project 中已有默认项目数据
|
||||
-- =============================================
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 1. iot_device
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE iot_device ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE iot_device d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE iot_device MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE iot_device ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 2. ops_order
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_order ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_order d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_order MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_order ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 3. ops_order_event
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_order_event ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_order_event d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_order_event MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_order_event ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 4. ops_order_dispatch
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_order_dispatch ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_order_dispatch d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_order_dispatch MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_order_dispatch ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 5. ops_order_queue
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_order_queue ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_order_queue d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_order_queue MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_order_queue ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 6. ops_bus_area
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_bus_area ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_bus_area d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_bus_area MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_bus_area ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 7. ops_area_device_relation
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_area_device_relation ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_area_device_relation d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_area_device_relation MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_area_device_relation ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 8. ops_order_security_ext
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_order_security_ext ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_order_security_ext d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_order_security_ext MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_order_security_ext ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 9. ops_area_security_user
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_area_security_user ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_area_security_user d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_area_security_user MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_area_security_user ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 10. ops_order_clean_ext
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_order_clean_ext ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_order_clean_ext d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_order_clean_ext MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_order_clean_ext ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 11. ops_cleaner_status
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_cleaner_status ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_cleaner_status d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_cleaner_status MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_cleaner_status ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 12. ops_cleaner_performance_monthly
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_cleaner_performance_monthly ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_cleaner_performance_monthly d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_cleaner_performance_monthly MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_cleaner_performance_monthly ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 13. ops_device_trajectory
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_device_trajectory ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_device_trajectory d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_device_trajectory MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_device_trajectory ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 14. ops_inspection_record
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_inspection_record ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_inspection_record d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_inspection_record MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_inspection_record ADD INDEX idx_project_id (project_id);
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 15. ops_inspection_record_item
|
||||
-- -----------------------------------------------
|
||||
ALTER TABLE ops_inspection_record_item ADD COLUMN project_id BIGINT NULL COMMENT '项目编号';
|
||||
|
||||
UPDATE ops_inspection_record_item d
|
||||
JOIN system_project p ON p.tenant_id = d.tenant_id AND p.code = 'DEFAULT' AND p.deleted = 0
|
||||
SET d.project_id = p.id
|
||||
WHERE d.project_id IS NULL;
|
||||
|
||||
ALTER TABLE ops_inspection_record_item MODIFY COLUMN project_id BIGINT NOT NULL COMMENT '项目编号';
|
||||
|
||||
ALTER TABLE ops_inspection_record_item ADD INDEX idx_project_id (project_id);
|
||||
86
sql/mysql/project/04-index-audit.sql
Normal file
86
sql/mysql/project/04-index-audit.sql
Normal file
@@ -0,0 +1,86 @@
|
||||
-- =============================================
|
||||
-- 租户-项目两级架构 - 唯一索引审计脚本
|
||||
-- 检查各业务表现有唯一键,评估是否需要将 project_id 纳入唯一约束
|
||||
-- 执行顺序:在 03-alter-business-tables.sql 之后执行
|
||||
-- =============================================
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 查看各表当前的索引情况(审计用,执行前先 SHOW INDEX 确认)
|
||||
-- -----------------------------------------------
|
||||
SHOW INDEX FROM iot_device;
|
||||
SHOW INDEX FROM ops_order;
|
||||
SHOW INDEX FROM ops_order_event;
|
||||
SHOW INDEX FROM ops_order_dispatch;
|
||||
SHOW INDEX FROM ops_order_queue;
|
||||
SHOW INDEX FROM ops_bus_area;
|
||||
SHOW INDEX FROM ops_area_device_relation;
|
||||
SHOW INDEX FROM ops_order_security_ext;
|
||||
SHOW INDEX FROM ops_area_security_user;
|
||||
SHOW INDEX FROM ops_order_clean_ext;
|
||||
SHOW INDEX FROM ops_cleaner_status;
|
||||
SHOW INDEX FROM ops_cleaner_performance_monthly;
|
||||
SHOW INDEX FROM ops_device_trajectory;
|
||||
SHOW INDEX FROM ops_inspection_record;
|
||||
SHOW INDEX FROM ops_inspection_record_item;
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 唯一键改造建议(根据实际业务语义决定是否执行)
|
||||
-- 说明:若某张表的唯一键仅含 tenant_id,则需要将 project_id 也纳入,
|
||||
-- 以确保在同一租户下不同项目之间的数据互不干扰。
|
||||
-- -----------------------------------------------
|
||||
|
||||
-- ops_bus_area:区域编码在项目内唯一(原唯一键可能仅含 tenant_id + code)
|
||||
-- 示例:DROP INDEX uk_tenant_code ON ops_bus_area;
|
||||
-- 示例:ALTER TABLE ops_bus_area ADD UNIQUE KEY uk_project_code (tenant_id, project_id, code, deleted);
|
||||
|
||||
-- ops_area_device_relation:设备-区域关联在项目内唯一
|
||||
-- 示例:DROP INDEX uk_area_device ON ops_area_device_relation;
|
||||
-- 示例:ALTER TABLE ops_area_device_relation ADD UNIQUE KEY uk_project_area_device (project_id, area_id, device_id, deleted);
|
||||
|
||||
-- ops_area_security_user:安保用户-区域关联在项目内唯一
|
||||
-- 示例:DROP INDEX uk_area_user ON ops_area_security_user;
|
||||
-- 示例:ALTER TABLE ops_area_security_user ADD UNIQUE KEY uk_project_area_user (project_id, area_id, user_id, deleted);
|
||||
|
||||
-- ops_cleaner_status:保洁员状态在项目内唯一(每个项目内每个用户仅一条状态记录)
|
||||
-- 示例:DROP INDEX uk_tenant_user ON ops_cleaner_status;
|
||||
-- 示例:ALTER TABLE ops_cleaner_status ADD UNIQUE KEY uk_project_user (project_id, user_id, deleted);
|
||||
|
||||
-- ops_cleaner_performance_monthly:月度绩效在项目内唯一(project + user + year_month)
|
||||
-- 示例:DROP INDEX uk_tenant_user_month ON ops_cleaner_performance_monthly;
|
||||
-- 示例:ALTER TABLE ops_cleaner_performance_monthly ADD UNIQUE KEY uk_project_user_month (project_id, user_id, stat_year, stat_month, deleted);
|
||||
|
||||
-- iot_device:设备标识符在项目内唯一(device_key / product_key + device_name)
|
||||
-- 示例:根据实际唯一键定义决定是否改造。
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 验证:各表 project_id 回填情况
|
||||
-- -----------------------------------------------
|
||||
SELECT 'iot_device' AS tbl, COUNT(*) AS total, SUM(project_id IS NULL) AS null_count FROM iot_device
|
||||
UNION ALL
|
||||
SELECT 'ops_order', COUNT(*), SUM(project_id IS NULL) FROM ops_order
|
||||
UNION ALL
|
||||
SELECT 'ops_order_event', COUNT(*), SUM(project_id IS NULL) FROM ops_order_event
|
||||
UNION ALL
|
||||
SELECT 'ops_order_dispatch', COUNT(*), SUM(project_id IS NULL) FROM ops_order_dispatch
|
||||
UNION ALL
|
||||
SELECT 'ops_order_queue', COUNT(*), SUM(project_id IS NULL) FROM ops_order_queue
|
||||
UNION ALL
|
||||
SELECT 'ops_bus_area', COUNT(*), SUM(project_id IS NULL) FROM ops_bus_area
|
||||
UNION ALL
|
||||
SELECT 'ops_area_device_relation', COUNT(*), SUM(project_id IS NULL) FROM ops_area_device_relation
|
||||
UNION ALL
|
||||
SELECT 'ops_order_security_ext', COUNT(*), SUM(project_id IS NULL) FROM ops_order_security_ext
|
||||
UNION ALL
|
||||
SELECT 'ops_area_security_user', COUNT(*), SUM(project_id IS NULL) FROM ops_area_security_user
|
||||
UNION ALL
|
||||
SELECT 'ops_order_clean_ext', COUNT(*), SUM(project_id IS NULL) FROM ops_order_clean_ext
|
||||
UNION ALL
|
||||
SELECT 'ops_cleaner_status', COUNT(*), SUM(project_id IS NULL) FROM ops_cleaner_status
|
||||
UNION ALL
|
||||
SELECT 'ops_cleaner_performance_monthly', COUNT(*), SUM(project_id IS NULL) FROM ops_cleaner_performance_monthly
|
||||
UNION ALL
|
||||
SELECT 'ops_device_trajectory', COUNT(*), SUM(project_id IS NULL) FROM ops_device_trajectory
|
||||
UNION ALL
|
||||
SELECT 'ops_inspection_record', COUNT(*), SUM(project_id IS NULL) FROM ops_inspection_record
|
||||
UNION ALL
|
||||
SELECT 'ops_inspection_record_item', COUNT(*), SUM(project_id IS NULL) FROM ops_inspection_record_item;
|
||||
46
sql/mysql/project/99-rollback.sql
Normal file
46
sql/mysql/project/99-rollback.sql
Normal file
@@ -0,0 +1,46 @@
|
||||
-- =============================================
|
||||
-- 租户-项目两级架构 - 回滚脚本
|
||||
-- 执行顺序与正向脚本相反:业务表 → 默认数据 → 建表
|
||||
-- =============================================
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- Step 1: 回滚业务表(删除 project_id 字段及索引)
|
||||
-- -----------------------------------------------
|
||||
|
||||
ALTER TABLE iot_device DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_order DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_order_event DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_order_dispatch DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_order_queue DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_bus_area DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_area_device_relation DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_order_security_ext DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_area_security_user DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_order_clean_ext DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_cleaner_status DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_cleaner_performance_monthly DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_device_trajectory DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_inspection_record DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
ALTER TABLE ops_inspection_record_item DROP INDEX idx_project_id, DROP COLUMN project_id;
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- Step 2: 回滚默认数据(删除用户-项目关联 和 默认项目)
|
||||
-- -----------------------------------------------
|
||||
|
||||
-- 删除系统自动生成的用户-项目关联
|
||||
DELETE FROM system_user_project WHERE creator = 'system' AND deleted = 0;
|
||||
|
||||
-- 删除系统自动生成的默认项目
|
||||
DELETE FROM system_project WHERE code = 'DEFAULT' AND creator = 'system' AND deleted = 0;
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- Step 3: 删除核心表
|
||||
-- -----------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS system_user_project;
|
||||
DROP TABLE IF EXISTS system_project;
|
||||
|
||||
-- -----------------------------------------------
|
||||
-- 验证
|
||||
-- -----------------------------------------------
|
||||
SELECT '回滚完成' AS status;
|
||||
@@ -17,6 +17,7 @@ import com.viewsh.framework.tenant.core.job.TenantJobAspect;
|
||||
import com.viewsh.framework.tenant.core.mq.rabbitmq.TenantRabbitMQInitializer;
|
||||
import com.viewsh.framework.tenant.core.mq.redis.TenantRedisMessageInterceptor;
|
||||
import com.viewsh.framework.tenant.core.mq.rocketmq.TenantRocketMQInitializer;
|
||||
import com.viewsh.framework.tenant.core.redis.ProjectRedisCacheManager;
|
||||
import com.viewsh.framework.tenant.core.redis.TenantRedisCacheManager;
|
||||
import com.viewsh.framework.tenant.core.security.TenantSecurityWebFilter;
|
||||
import com.viewsh.framework.tenant.core.service.ProjectFrameworkService;
|
||||
@@ -266,8 +267,9 @@ public class ViewshTenantAutoConfiguration {
|
||||
RedisConnectionFactory connectionFactory = Objects.requireNonNull(redisTemplate.getConnectionFactory());
|
||||
RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory,
|
||||
BatchStrategies.scan(viewshCacheProperties.getRedisScanBatchSize()));
|
||||
// 创建 TenantRedisCacheManager 对象
|
||||
return new TenantRedisCacheManager(cacheWriter, redisCacheConfiguration, tenantProperties.getIgnoreCaches());
|
||||
// 创建 ProjectRedisCacheManager 对象(在租户隔离基础上叠加项目隔离)
|
||||
return new ProjectRedisCacheManager(cacheWriter, redisCacheConfiguration,
|
||||
tenantProperties.getIgnoreCaches(), tenantProperties.getIgnoreProjectCaches());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.viewsh.framework.tenant.core.redis;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.viewsh.framework.tenant.core.context.ProjectContextHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.data.redis.cache.RedisCacheConfiguration;
|
||||
import org.springframework.data.redis.cache.RedisCacheWriter;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 多项目的 {@link org.springframework.data.redis.cache.RedisCacheManager} 实现类
|
||||
*
|
||||
* 在租户隔离的基础上,追加项目隔离后缀,格式为 name + ":" + tenantId + ":" + projectId
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
@Slf4j
|
||||
public class ProjectRedisCacheManager extends TenantRedisCacheManager {
|
||||
|
||||
private static final String SPLIT = "#";
|
||||
|
||||
private final Set<String> ignoreProjectCaches;
|
||||
|
||||
public ProjectRedisCacheManager(RedisCacheWriter cacheWriter,
|
||||
RedisCacheConfiguration defaultCacheConfiguration,
|
||||
Set<String> ignoreTenantCaches,
|
||||
Set<String> ignoreProjectCaches) {
|
||||
super(cacheWriter, defaultCacheConfiguration, ignoreTenantCaches);
|
||||
this.ignoreProjectCaches = ignoreProjectCaches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cache getCache(String name) {
|
||||
// 获取原始 cache name(去掉 # 后缀部分,# 后面是超时配置)
|
||||
String[] names = StrUtil.splitToArray(name, SPLIT);
|
||||
// 如果开启项目隔离,则在 name 上追加 projectId 后缀
|
||||
// 父类 TenantRedisCacheManager.getCache 会继续追加 tenantId,
|
||||
// 最终 key 格式:name[:projectId]:tenantId
|
||||
if (!ProjectContextHolder.isIgnore()
|
||||
&& ProjectContextHolder.getProjectId() != null
|
||||
&& !CollUtil.contains(ignoreProjectCaches, names[0])) {
|
||||
name = name + ":" + ProjectContextHolder.getProjectId();
|
||||
}
|
||||
// 继续基于父方法(父类追加租户后缀)
|
||||
return super.getCache(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,10 @@ public class IotDeviceRespDTO {
|
||||
* 租户编号
|
||||
*/
|
||||
private Long tenantId;
|
||||
/**
|
||||
* 项目编号
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
// ========== 产品相关字段 ==========
|
||||
|
||||
|
||||
@@ -54,6 +54,10 @@ public class IotDeviceMessage {
|
||||
* 租户编号
|
||||
*/
|
||||
private Long tenantId;
|
||||
/**
|
||||
* 项目编号
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 服务编号,该消息由哪个 server 发送
|
||||
|
||||
@@ -1,138 +1,139 @@
|
||||
package com.viewsh.module.iot.gateway.service.device.message;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.viewsh.framework.common.util.collection.CollectionUtils;
|
||||
import com.viewsh.module.iot.core.biz.dto.IotDeviceRespDTO;
|
||||
import com.viewsh.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import com.viewsh.module.iot.core.mq.producer.IotDeviceMessageProducer;
|
||||
import com.viewsh.module.iot.core.util.IotDeviceMessageUtils;
|
||||
import com.viewsh.module.iot.gateway.codec.IotDeviceMessageCodec;
|
||||
import com.viewsh.module.iot.gateway.service.device.IotDeviceService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.viewsh.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static com.viewsh.module.iot.gateway.enums.ErrorCodeConstants.DEVICE_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* IoT 设备消息 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class IotDeviceMessageServiceImpl implements IotDeviceMessageService {
|
||||
|
||||
/**
|
||||
* 编解码器
|
||||
*/
|
||||
private final Map<String, IotDeviceMessageCodec> codes;
|
||||
|
||||
@Resource
|
||||
private IotDeviceService deviceService;
|
||||
|
||||
@Resource
|
||||
private IotDeviceMessageProducer deviceMessageProducer;
|
||||
|
||||
public IotDeviceMessageServiceImpl(List<IotDeviceMessageCodec> codes) {
|
||||
this.codes = CollectionUtils.convertMap(codes, IotDeviceMessageCodec::type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeDeviceMessage(IotDeviceMessage message,
|
||||
String productKey, String deviceName) {
|
||||
// 1.1 获取设备信息
|
||||
IotDeviceRespDTO device = deviceService.getDeviceFromCache(productKey, deviceName);
|
||||
if (device == null) {
|
||||
throw exception(DEVICE_NOT_EXISTS, productKey, deviceName);
|
||||
}
|
||||
// 1.2 获取编解码器
|
||||
IotDeviceMessageCodec codec = codes.get(device.getCodecType());
|
||||
if (codec == null) {
|
||||
throw new IllegalArgumentException(StrUtil.format("编解码器({}) 不存在", device.getCodecType()));
|
||||
}
|
||||
|
||||
// 2. 编码消息
|
||||
return codec.encode(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeDeviceMessage(IotDeviceMessage message,
|
||||
String codecType) {
|
||||
// 1. 获取编解码器
|
||||
IotDeviceMessageCodec codec = codes.get(codecType);
|
||||
if (codec == null) {
|
||||
throw new IllegalArgumentException(StrUtil.format("编解码器({}) 不存在", codecType));
|
||||
}
|
||||
|
||||
// 2. 编码消息
|
||||
return codec.encode(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IotDeviceMessage decodeDeviceMessage(byte[] bytes,
|
||||
String productKey, String deviceName) {
|
||||
// 1.1 获取设备信息
|
||||
IotDeviceRespDTO device = deviceService.getDeviceFromCache(productKey, deviceName);
|
||||
if (device == null) {
|
||||
throw exception(DEVICE_NOT_EXISTS, productKey, deviceName);
|
||||
}
|
||||
// 1.2 获取编解码器
|
||||
IotDeviceMessageCodec codec = codes.get(device.getCodecType());
|
||||
if (codec == null) {
|
||||
throw new IllegalArgumentException(StrUtil.format("编解码器({}) 不存在", device.getCodecType()));
|
||||
}
|
||||
|
||||
// 2. 解码消息
|
||||
return codec.decode(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IotDeviceMessage decodeDeviceMessage(byte[] bytes, String codecType) {
|
||||
// 1. 获取编解码器
|
||||
IotDeviceMessageCodec codec = codes.get(codecType);
|
||||
if (codec == null) {
|
||||
throw new IllegalArgumentException(StrUtil.format("编解码器({}) 不存在", codecType));
|
||||
}
|
||||
|
||||
// 2. 解码消息
|
||||
return codec.decode(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDeviceMessage(IotDeviceMessage message,
|
||||
String productKey, String deviceName, String serverId) {
|
||||
// 1. 获取设备信息
|
||||
IotDeviceRespDTO device = deviceService.getDeviceFromCache(productKey, deviceName);
|
||||
if (device == null) {
|
||||
throw exception(DEVICE_NOT_EXISTS, productKey, deviceName);
|
||||
}
|
||||
|
||||
// 2. 发送消息
|
||||
appendDeviceMessage(message, device, serverId);
|
||||
deviceMessageProducer.sendDeviceMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 补充消息的后端字段
|
||||
*
|
||||
* @param message 消息
|
||||
* @param device 设备信息
|
||||
* @param serverId 设备连接的 serverId
|
||||
*/
|
||||
private void appendDeviceMessage(IotDeviceMessage message,
|
||||
IotDeviceRespDTO device, String serverId) {
|
||||
message.setId(IotDeviceMessageUtils.generateMessageId()).setReportTime(LocalDateTime.now())
|
||||
.setDeviceId(device.getId()).setTenantId(device.getTenantId()).setServerId(serverId);
|
||||
// 特殊:如果设备没有指定 requestId,则使用 messageId
|
||||
if (StrUtil.isEmpty(message.getRequestId())) {
|
||||
message.setRequestId(message.getId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package com.viewsh.module.iot.gateway.service.device.message;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.viewsh.framework.common.util.collection.CollectionUtils;
|
||||
import com.viewsh.module.iot.core.biz.dto.IotDeviceRespDTO;
|
||||
import com.viewsh.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import com.viewsh.module.iot.core.mq.producer.IotDeviceMessageProducer;
|
||||
import com.viewsh.module.iot.core.util.IotDeviceMessageUtils;
|
||||
import com.viewsh.module.iot.gateway.codec.IotDeviceMessageCodec;
|
||||
import com.viewsh.module.iot.gateway.service.device.IotDeviceService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.viewsh.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static com.viewsh.module.iot.gateway.enums.ErrorCodeConstants.DEVICE_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* IoT 设备消息 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class IotDeviceMessageServiceImpl implements IotDeviceMessageService {
|
||||
|
||||
/**
|
||||
* 编解码器
|
||||
*/
|
||||
private final Map<String, IotDeviceMessageCodec> codes;
|
||||
|
||||
@Resource
|
||||
private IotDeviceService deviceService;
|
||||
|
||||
@Resource
|
||||
private IotDeviceMessageProducer deviceMessageProducer;
|
||||
|
||||
public IotDeviceMessageServiceImpl(List<IotDeviceMessageCodec> codes) {
|
||||
this.codes = CollectionUtils.convertMap(codes, IotDeviceMessageCodec::type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeDeviceMessage(IotDeviceMessage message,
|
||||
String productKey, String deviceName) {
|
||||
// 1.1 获取设备信息
|
||||
IotDeviceRespDTO device = deviceService.getDeviceFromCache(productKey, deviceName);
|
||||
if (device == null) {
|
||||
throw exception(DEVICE_NOT_EXISTS, productKey, deviceName);
|
||||
}
|
||||
// 1.2 获取编解码器
|
||||
IotDeviceMessageCodec codec = codes.get(device.getCodecType());
|
||||
if (codec == null) {
|
||||
throw new IllegalArgumentException(StrUtil.format("编解码器({}) 不存在", device.getCodecType()));
|
||||
}
|
||||
|
||||
// 2. 编码消息
|
||||
return codec.encode(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeDeviceMessage(IotDeviceMessage message,
|
||||
String codecType) {
|
||||
// 1. 获取编解码器
|
||||
IotDeviceMessageCodec codec = codes.get(codecType);
|
||||
if (codec == null) {
|
||||
throw new IllegalArgumentException(StrUtil.format("编解码器({}) 不存在", codecType));
|
||||
}
|
||||
|
||||
// 2. 编码消息
|
||||
return codec.encode(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IotDeviceMessage decodeDeviceMessage(byte[] bytes,
|
||||
String productKey, String deviceName) {
|
||||
// 1.1 获取设备信息
|
||||
IotDeviceRespDTO device = deviceService.getDeviceFromCache(productKey, deviceName);
|
||||
if (device == null) {
|
||||
throw exception(DEVICE_NOT_EXISTS, productKey, deviceName);
|
||||
}
|
||||
// 1.2 获取编解码器
|
||||
IotDeviceMessageCodec codec = codes.get(device.getCodecType());
|
||||
if (codec == null) {
|
||||
throw new IllegalArgumentException(StrUtil.format("编解码器({}) 不存在", device.getCodecType()));
|
||||
}
|
||||
|
||||
// 2. 解码消息
|
||||
return codec.decode(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IotDeviceMessage decodeDeviceMessage(byte[] bytes, String codecType) {
|
||||
// 1. 获取编解码器
|
||||
IotDeviceMessageCodec codec = codes.get(codecType);
|
||||
if (codec == null) {
|
||||
throw new IllegalArgumentException(StrUtil.format("编解码器({}) 不存在", codecType));
|
||||
}
|
||||
|
||||
// 2. 解码消息
|
||||
return codec.decode(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDeviceMessage(IotDeviceMessage message,
|
||||
String productKey, String deviceName, String serverId) {
|
||||
// 1. 获取设备信息
|
||||
IotDeviceRespDTO device = deviceService.getDeviceFromCache(productKey, deviceName);
|
||||
if (device == null) {
|
||||
throw exception(DEVICE_NOT_EXISTS, productKey, deviceName);
|
||||
}
|
||||
|
||||
// 2. 发送消息
|
||||
appendDeviceMessage(message, device, serverId);
|
||||
deviceMessageProducer.sendDeviceMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 补充消息的后端字段
|
||||
*
|
||||
* @param message 消息
|
||||
* @param device 设备信息
|
||||
* @param serverId 设备连接的 serverId
|
||||
*/
|
||||
private void appendDeviceMessage(IotDeviceMessage message,
|
||||
IotDeviceRespDTO device, String serverId) {
|
||||
message.setId(IotDeviceMessageUtils.generateMessageId()).setReportTime(LocalDateTime.now())
|
||||
.setDeviceId(device.getId()).setTenantId(device.getTenantId())
|
||||
.setProjectId(device.getProjectId()).setServerId(serverId);
|
||||
// 特殊:如果设备没有指定 requestId,则使用 messageId
|
||||
if (StrUtil.isEmpty(message.getRequestId())) {
|
||||
message.setRequestId(message.getId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.viewsh.module.iot.dal.dataobject.device;
|
||||
|
||||
import com.viewsh.framework.mybatis.core.type.LongSetTypeHandler;
|
||||
import com.viewsh.framework.tenant.core.db.TenantBaseDO;
|
||||
import com.viewsh.framework.tenant.core.db.ProjectBaseDO;
|
||||
import com.viewsh.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
|
||||
import com.viewsh.module.iot.dal.dataobject.product.IotProductDO;
|
||||
import com.viewsh.module.iot.core.enums.IotDeviceStateEnum;
|
||||
@@ -26,7 +26,7 @@ import java.util.Set;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IotDeviceDO extends TenantBaseDO {
|
||||
public class IotDeviceDO extends ProjectBaseDO {
|
||||
|
||||
/**
|
||||
* 设备编号 - 全部设备
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.viewsh.module.iot.mq.consumer.rule;
|
||||
|
||||
import com.viewsh.framework.tenant.core.util.ProjectUtils;
|
||||
import com.viewsh.framework.tenant.core.util.TenantUtils;
|
||||
import com.viewsh.module.iot.core.messagebus.core.IotMessageBus;
|
||||
import com.viewsh.module.iot.core.messagebus.core.IotMessageSubscriber;
|
||||
@@ -50,12 +51,14 @@ public class IotCleanRuleMessageHandler implements IotMessageSubscriber<IotDevic
|
||||
@Override
|
||||
public void onMessage(IotDeviceMessage message) {
|
||||
TenantUtils.execute(message.getTenantId(), () -> {
|
||||
try {
|
||||
cleanRuleProcessorManager.processMessage(message);
|
||||
} catch (Exception e) {
|
||||
// 规则处理异常不影响其他消息处理
|
||||
log.error("[onMessage][消息({}) 保洁规则处理异常]", message.getRequestId(), e);
|
||||
}
|
||||
ProjectUtils.execute(message.getProjectId(), () -> {
|
||||
try {
|
||||
cleanRuleProcessorManager.processMessage(message);
|
||||
} catch (Exception e) {
|
||||
// 规则处理异常不影响其他消息处理
|
||||
log.error("[onMessage][消息({}) 保洁规则处理异常]", message.getRequestId(), e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.viewsh.module.ops.environment.dal.dataobject.cleaner;
|
||||
|
||||
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.math.BigDecimal;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OpsCleanerPerformanceMonthlyDO extends TenantBaseDO {
|
||||
public class OpsCleanerPerformanceMonthlyDO extends ProjectBaseDO {
|
||||
|
||||
/**
|
||||
* 汇总ID
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.viewsh.framework.tenant.core.db.TenantBaseDO;
|
||||
import com.viewsh.framework.tenant.core.db.ProjectBaseDO;
|
||||
import com.viewsh.module.ops.enums.CleanerStatusEnum;
|
||||
import lombok.*;
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.time.LocalDateTime;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OpsCleanerStatusDO extends TenantBaseDO {
|
||||
public class OpsCleanerStatusDO extends ProjectBaseDO {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.viewsh.module.ops.environment.dal.dataobject.inspection;
|
||||
|
||||
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.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
@@ -21,7 +21,7 @@ import java.util.List;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OpsInspectionRecordDO extends TenantBaseDO {
|
||||
public class OpsInspectionRecordDO extends ProjectBaseDO {
|
||||
|
||||
/**
|
||||
* 巡检记录ID
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.viewsh.module.ops.environment.dal.dataobject.inspection;
|
||||
|
||||
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.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
@@ -21,7 +21,7 @@ import java.util.List;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OpsInspectionRecordItemDO extends TenantBaseDO {
|
||||
public class OpsInspectionRecordItemDO extends ProjectBaseDO {
|
||||
|
||||
/**
|
||||
* 明细ID
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.viewsh.module.ops.environment.dal.dataobject.workorder;
|
||||
|
||||
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.*;
|
||||
@@ -19,7 +19,7 @@ import java.time.LocalDateTime;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OpsOrderCleanExtDO extends TenantBaseDO {
|
||||
public class OpsOrderCleanExtDO extends ProjectBaseDO {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
|
||||
@@ -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 {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
|
||||
@@ -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,主键
|
||||
|
||||
@@ -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(主键)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>花算法生成)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.viewsh.module.ops.security.dal.dataobject.area;
|
||||
|
||||
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.*;
|
||||
@@ -17,7 +17,7 @@ import lombok.*;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OpsAreaSecurityUserDO extends TenantBaseDO {
|
||||
public class OpsAreaSecurityUserDO extends ProjectBaseDO {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.viewsh.module.ops.security.dal.dataobject.workorder;
|
||||
|
||||
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.*;
|
||||
@@ -19,7 +19,7 @@ import java.time.LocalDateTime;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OpsOrderSecurityExtDO extends TenantBaseDO {
|
||||
public class OpsOrderSecurityExtDO extends ProjectBaseDO {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
|
||||
Reference in New Issue
Block a user