背景: 规则动作 params 的 key 会被原样当作涂鸦 code 下发(dp_id 从不参与下发), 历史测试数据里出现过 switch_1 与 1 混用, 导致下发失败或指令相互矛盾, 且保存时无任何校验。 后端: 新增 RuleActionValidator, createRule/updateRule 前校验动作参数 key 必须命中 product_property.code; 命中 dp_id 时直接提示应改用的 code; 同步校验值域(bool 取值、数值 min/max 区间、enum 候选值); 目标设备不存在、无产品物模型等场景给出明确业务错误。 前端: 后台规则表单补齐执行动作编辑(JSON), 提交前本地解析校验, 原本表单不提交 actions 导致新建规则必然失败。 Android: 物模型不可用时的回退路径改为优先使用涂鸦 code(反射读取), 避免提交 dpId 被后端拒绝。 V24: scene_run 表不存在时容错跳过, 便于在未执行 V16 的旧结构库上整段执行。
61 lines
3.1 KiB
SQL
61 lines
3.1 KiB
SQL
-- =====================================================================
|
||
-- V24 · 清理测试阶段遗留的孤儿涂鸦设备与测试联动数据
|
||
-- ---------------------------------------------------------------------
|
||
-- 背景:
|
||
-- 1) unbindUser 早期只物理删除 tuya_user_binding 绑定记录,不处理已同步的设备,
|
||
-- 于是产生"孤儿涂鸦设备":设备仍在设备列表,却已无涂鸦账号可控制。
|
||
-- 定时场景每分钟命中的联动规则会持续对它们下发指令,全部失败并刷错误日志。
|
||
-- (代码侧已修复:解绑时联动逻辑删除设备与 AI 档案,重新绑定同步时自动恢复)
|
||
-- 2) 测试阶段遗留的联动规则与场景:条件全部相同(switch_1 == true)但动作互相矛盾
|
||
-- (switch_1=true / switch_1=0 / {"1":"open"} 混用 dpId),会下发自相矛盾的指令。
|
||
--
|
||
-- 清理范围:
|
||
-- - 逻辑删除孤儿涂鸦设备(owner 已无涂鸦绑定记录)
|
||
-- - 逻辑删除指向这些设备的 AI 档案
|
||
-- - 删除测试联动规则与测试场景(含每分钟 cron 的 bb 场景)
|
||
-- 保留:产品与物模型(product / product_property / product_event / product_action),
|
||
-- 家庭与成员、设备活动日志(历史审计)等。
|
||
--
|
||
-- 无存储过程、无 DELIMITER;幂等可重复执行。
|
||
-- =====================================================================
|
||
|
||
-- ---------- 1) 逻辑删除孤儿涂鸦设备 ----------
|
||
UPDATE device d
|
||
SET d.deleted = 1,
|
||
d.update_time = NOW()
|
||
WHERE d.deleted = 0
|
||
AND d.platform = 'tuya'
|
||
AND d.owner_id > 0
|
||
AND NOT EXISTS (SELECT 1 FROM tuya_user_binding b WHERE b.member_id = d.owner_id);
|
||
|
||
-- ---------- 2) 逻辑删除已解绑用户的 AI 档案 ----------
|
||
-- 注意:这里按 owner_id 判定,而不是 JOIN device 比较 device_id——
|
||
-- ai_device_profile.device_id 与 device.device_id 的排序规则不同
|
||
-- (utf8mb4_unicode_ci vs utf8mb4_0900_ai_ci),跨表字符串比较会报
|
||
-- ERROR 1267 Illegal mix of collations。owner_id 为数值列,无此问题。
|
||
UPDATE ai_device_profile a
|
||
SET a.deleted = 1,
|
||
a.update_time = NOW()
|
||
WHERE a.deleted = 0
|
||
AND a.owner_id > 0
|
||
AND NOT EXISTS (SELECT 1 FROM tuya_user_binding b WHERE b.member_id = a.owner_id);
|
||
|
||
-- ---------- 3) 删除测试联动规则 ----------
|
||
DELETE FROM linkage_rule WHERE deleted = 0;
|
||
|
||
-- ---------- 4) 删除测试场景(bb 场景 cron 为每分钟执行) ----------
|
||
DELETE FROM scene WHERE deleted = 0;
|
||
|
||
-- ---------- 5) 清理场景执行记录 ----------
|
||
-- scene_run 表在部分环境(未执行 V16 的库)不存在,用动态 SQL 做存在性判断后再清理,
|
||
-- 保证迁移在"旧结构库"上也能整段跑完而不中断。
|
||
SET @has_scene_run = (SELECT COUNT(*) FROM information_schema.TABLES
|
||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'scene_run');
|
||
SET @s = IF(@has_scene_run > 0,
|
||
'DELETE FROM scene_run',
|
||
'SELECT ''scene_run table not found, skipped'' AS info');
|
||
PREPARE stmt FROM @s;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|