SCSAI 元数据同步与规则模板更新系统

SCSAI 元数据同步与规则模板更新系统

版本: v1.0 | 创建: 2026-05-29 | 状态: 设计阶段


1. 问题分析

1.1 当前架构的局限性

问题影响严重程度
AML 文件是静态快照SCSAI 服务端变更后,本地规则模板过时P0
无变更检测机制不知道 SCSAI 何时新增/修改/删除了什么P0
无版本管理无法追踪规则模板的历史变更,无法回滚P1
无增量同步每次都要全量重新导入,效率低,耗时长P1
无冲突处理SCSAI 修改和本地修改冲突时,无法智能合并P2

1.2 变更场景分析

场景SCSAI 操作本地影响同步策略
新增对象类创建 ItemType需要新增规则模板、提示词自动同步
修改对象类修改属性、新增字段需要更新规则模板、提示词需审核
删除对象类删除 ItemType需要标记删除或归档需审核
新增列表值List 新增 Value需要更新可选值列表自动同步
修改列表值修改 Value 的 label需要更新可选值列表自动同步
删除列表值删除 Value需要更新可选值列表需审核
新增关系创建 RelationshipType需要新增关系模板自动同步
修改关系修改关系属性需要更新关系模板需审核
修改提示词本地管理员修改与 SCSAI 变更可能冲突冲突检测

2. 系统架构设计

2.1 整体架构

┌─────────────────────────────────────────────────────────────────────────────┐
│                            SCSAI 服务端                                       │
│              (ItemType, Property, List, Relationship, Value)                 │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                                    │ ① Webhook / 定时轮询
                                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                         变更检测层 (Change Detection)                        │
├─────────────────────────────────────────────────────────────────────────────┤
│  • 元数据版本表 (SCSAI_metadata_versions)                                     │
│  • 变更队列 (sync_queue)                                                      │
│  • 变更检测算法 (detectChanges)                                               │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                                    │ ② 生成同步任务
                                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                         增量同步层 (Incremental Sync)                        │
├─────────────────────────────────────────────────────────────────────────────┤
│  • 同步任务处理器 (processSyncQueue)                                          │
│  • 增量导入逻辑 (syncItemTypeFromSCSAI)                                        │
│  • 批量处理与重试机制                                                         │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                                    │ ③ 更新本地数据
                                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                       规则模板管理层 (Template Management)                    │
├─────────────────────────────────────────────────────────────────────────────┤
│  • 版本控制 (sciot_item_type_versions)                                       │
│  • 草稿/发布状态管理                                                          │
│  • 冲突检测与人工审核                                                         │
│  • 规则模板自动生成                                                           │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                                    │ ④ 通知
                                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                         通知层 (Notification)                                │
├─────────────────────────────────────────────────────────────────────────────┤
│  • 飞书通知 (变更、冲突、失败)                                                 │
│  • 邮件通知                                                                   │
│  • 系统内通知                                                                 │
└─────────────────────────────────────────────────────────────────────────────┘

2.2 数据流图

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│  SCSAI 服务端  │────▶│  变更检测层   │────▶│  同步队列     │
└──────────────┘     └──────────────┘     └──────────────┘
                            │                     │
                            ▼                     ▼
                     ┌──────────────┐     ┌──────────────┐
                     │  版本对比     │     │  任务处理     │
                     └──────────────┘     └──────────────┘
                            │                     │
                            ▼                     ▼
                     ┌──────────────┐     ┌──────────────┐
                     │  冲突检测     │     │  增量导入     │
                     └──────────────┘     └──────────────┘
                            │                     │
                            ▼                     ▼
                     ┌──────────────┐     ┌──────────────┐
                     │  人工审核     │     │  更新本地     │
                     └──────────────┘     └──────────────┘
                            │                     │
                            └──────────┬──────────┘
                                       ▼
                                ┌──────────────┐
                                │  通知用户     │
                                └──────────────┘

3. 数据库设计

3.1 新增表结构

#### 3.1.1 SCSAI_metadata_versions - SCSAI 元数据版本追踪

CREATE TABLE SCSAI_metadata_versions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    
    -- 对象标识
    item_type_name TEXT NOT NULL,              -- 对象类名称
    item_type_id TEXT,                         -- SCSAI 中的 ID
    
    -- SCSAI 版本信息
    SCSAI_config_id TEXT,                       -- SCSAI config_id(用于检测变更)
    SCSAI_modified_on TEXT,                     -- SCSAI 最后修改时间
    SCSAI_generation INTEGER,                   -- SCSAI generation(版本号)
    
    -- 本地版本信息
    local_synced_at TEXT,                      -- 本地最后同步时间
    local_version INTEGER DEFAULT 1,           -- 本地版本号
    
    -- 变更检测
    change_type TEXT DEFAULT 'NONE',           -- NONE/ADD/MODIFY/DELETE
    change_detected_at TEXT,                   -- 检测到变更的时间
    change_details TEXT,                       -- 变更详情 JSON
    
    -- 同步状态
    sync_status TEXT DEFAULT 'synced',         -- synced/pending/syncing/failed/conflict
    last_sync_error TEXT,                      -- 最后同步错误
    
    created_at TEXT DEFAULT CURRENT_TIMESTAMP,
    updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
    
    UNIQUE(item_type_name)
);

CREATE INDEX idx_metadata_sync_status ON SCSAI_metadata_versions(sync_status);
CREATE INDEX idx_metadata_change_type ON SCSAI_metadata_versions(change_type);

#### 3.1.2 sync_queue - 同步任务队列

CREATE TABLE sync_queue (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    
    -- 任务标识
    task_type TEXT NOT NULL,                   -- ITEMTYPE/LIST/RELATIONSHIP/PROPERTY
    task_action TEXT NOT NULL,                 -- ADD/MODIFY/DELETE/REFRESH
    target_name TEXT NOT NULL,                 -- 目标对象名称
    target_id TEXT,                            -- 目标对象 ID
    
    -- 任务优先级
    priority INTEGER DEFAULT 5,                -- 1-10,1 最高
    
    -- 任务状态
    status TEXT DEFAULT 'pending',             -- pending/processing/done/failed/needs_review
    retry_count INTEGER DEFAULT 0,
    max_retry INTEGER DEFAULT 3,
    
    -- 任务数据
    task_data TEXT,                            -- 任务数据 JSON
    result_data TEXT,                          -- 执行结果 JSON
    error_msg TEXT,                            -- 错误信息
    
    -- 审核相关
    needs_review INTEGER DEFAULT 0,            -- 是否需要人工审核
    review_reason TEXT,                        -- 审核原因
    reviewed_by TEXT,                          -- 审核人
    reviewed_at TEXT,                          -- 审核时间
    review_action TEXT,                        -- 审核决定: approve/reject/modify
    
    created_at TEXT DEFAULT CURRENT_TIMESTAMP,
    started_at TEXT,
    completed_at TEXT
);

CREATE INDEX idx_sync_queue_status ON sync_queue(status);
CREATE INDEX idx_sync_queue_priority ON sync_queue(priority, created_at);

#### 3.1.3 sciot_item_type_versions - 规则模板版本历史

CREATE TABLE sciot_item_type_versions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    
    -- 版本标识
    item_type_name TEXT NOT NULL,
    version INTEGER NOT NULL,
    
    -- 版本来源
    version_source TEXT DEFAULT 'manual',      -- manual/auto_sync/import/rollback
    version_reason TEXT,                       -- 版本变更原因
    
    -- 版本状态
    status TEXT DEFAULT 'draft',               -- draft/published/deprecated/archived
    
    -- 快照数据
    properties_snapshot TEXT,                  -- 属性快照 JSON
    rules_snapshot TEXT,                       -- 规则快照 JSON
    prompts_snapshot TEXT,                     -- 提示词快照 JSON
    template_snapshot TEXT,                    -- 模板快照 JSON
    relationships_snapshot TEXT,               -- 关系快照 JSON
    
    -- 变更摘要
    change_summary TEXT,                       -- 变更摘要
    change_details TEXT,                       -- 详细变更 JSON
    
    -- 审核相关
    created_by TEXT DEFAULT 'system',          -- 创建者: system/admin/用户名
    reviewed_by TEXT,                          -- 审核人
    reviewed_at TEXT,
    
    created_at TEXT DEFAULT CURRENT_TIMESTAMP,
    published_at TEXT,
    
    UNIQUE(item_type_name, version)
);

CREATE INDEX idx_versions_item_type ON sciot_item_type_versions(item_type_name);
CREATE INDEX idx_versions_status ON sciot_item_type_versions(status);

#### 3.1.4 sync_conflicts - 冲突记录

CREATE TABLE sync_conflicts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    
    -- 冲突标识
    item_type_name TEXT NOT NULL,
    field_name TEXT,                           -- 冲突字段
    conflict_type TEXT NOT NULL,               -- FIELD_MODIFIED/FIELD_DELETED/RULE_MODIFIED
    
    -- SCSAI 端数据
    SCSAI_value TEXT,                           -- SCSAI 当前值 JSON
    SCSAI_modified_on TEXT,                     -- SCSAI 修改时间
    
    -- 本地数据
    local_value TEXT,                          -- 本地当前值 JSON
    local_modified_on TEXT,                    -- 本地修改时间
    local_modified_by TEXT,                    -- 本地修改人
    
    -- 解决方案
    resolution TEXT DEFAULT 'pending',         -- pending/use_SCSAI/use_local/merge/custom
    resolved_value TEXT,                       -- 解决后的值 JSON
    resolved_by TEXT,                          -- 解决人
    resolved_at TEXT,                          -- 解决时间
    
    created_at TEXT DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_conflicts_resolution ON sync_conflicts(resolution);

#### 3.1.5 sync_logs - 同步日志

CREATE TABLE sync_logs (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    
    -- 日志标识
    log_type TEXT NOT NULL,                    -- DETECT/SYNC/CONFLICT/ERROR
    log_level TEXT DEFAULT 'info',             -- debug/info/warn/error
    
    -- 日志内容
    message TEXT NOT NULL,
    details TEXT,                              -- 详细信息 JSON
    
    -- 关联对象
    item_type_name TEXT,
    task_id INTEGER,                           -- 关联 sync_queue.id
    
    created_at TEXT DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_sync_logs_type ON sync_logs(log_type, created_at);

3.2 现有表扩展

#### 3.2.1 sciot_item_types 表扩展

ALTER TABLE sciot_item_types ADD COLUMN sync_status TEXT DEFAULT 'synced';
ALTER TABLE sciot_item_types ADD COLUMN SCSAI_modified_on TEXT;
ALTER TABLE sciot_item_types ADD COLUMN local_modified_on TEXT;
ALTER TABLE sciot_item_types ADD COLUMN is_deleted INTEGER DEFAULT 0;
ALTER TABLE sciot_item_types ADD COLUMN deleted_at TEXT;

#### 3.2.2 sciot_properties 表扩展

ALTER TABLE sciot_properties ADD COLUMN sync_status TEXT DEFAULT 'synced';
ALTER TABLE sciot_properties ADD COLUMN SCSAI_modified_on TEXT;
ALTER TABLE sciot_properties ADD COLUMN local_modified_on TEXT;

4. 核心算法设计

4.1 变更检测算法

/**
 * 变更检测算法
 * 
 * 输入: SCSAI 元数据快照、本地版本记录
 * 输出: 变更列表 [{ type, item, local, details }]
 */

async function detectChanges(options = {}) {
    const { 
        itemTypes = null,      // 指定检测的对象类,null 表示全部
        forceFullScan = false  // 是否强制全量扫描
    } = options;
    
    const changes = [];
    
    // 1. 从 SCSAI 获取元数据摘要
    const SCSAIMetadata = await fetchSCSAIMetadataSummary(itemTypes);
    
    // 2. 获取本地版本记录
    const localVersions = db.prepare('SELECT * FROM SCSAI_metadata_versions').all();
    const localMap = new Map(localVersions.map(v => [v.item_type_name, v]));
    
    // 3. 检测新增和修改
    for (const SCSAIItem of SCSAIMetadata) {
        const local = localMap.get(SCSAIItem.name);
        
        if (!local) {
            // 新增
            changes.push({
                type: 'ADD',
                item: SCSAIItem,
                details: { reason: 'SCSAI 新增对象类' }
            });
        } else {
            // 检测是否修改
            const isModified = await detectItemModification(SCSAIItem, local);
            if (isModified) {
                changes.push({
                    type: 'MODIFY',
                    item: SCSAIItem,
                    local: local,
                    details: isModified
                });
            }
        }
    }
    
    // 4. 检测删除
    for (const local of localVersions) {
        if (!SCSAIMetadata.find(a => a.name === local.item_type_name)) {
            changes.push({
                type: 'DELETE',
                local: local,
                details: { reason: 'SCSAI 已删除对象类' }
            });
        }
    }
    
    // 5. 写入变更检测日志
    await logChanges(changes);
    
    return changes;
}

/**
 * 检测单个对象类是否被修改
 */
async function detectItemModification(SCSAIItem, local) {
    // 快速检测:比较 config_id 和 modified_on
    if (SCSAIItem.config_id !== local.SCSAI_config_id ||
        SCSAIItem.modified_on !== local.SCSAI_modified_on) {
        
        // 详细对比
        const details = await compareItemDetails(SCSAIItem.name);
        return details;
    }
    
    return null; // 无变更
}

/**
 * 详细对比对象类属性
 */
async function compareItemDetails(itemTypeName) {
    // 从 SCSAI 获取完整属性
    const SCSAIProps = await fetchSCSAIItemProperties(itemTypeName);
    
    // 从本地获取属性
    const localProps = db.prepare(
        'SELECT * FROM sciot_properties WHERE item_type_name = ?'
    ).all(itemTypeName);
    
    const changes = {
        addedProperties: [],
        modifiedProperties: [],
        deletedProperties: [],
        listValueChanged: [],
        relationshipChanged: []
    };
    
    const localMap = new Map(localProps.map(p => [p.name, p]));
    const SCSAIMap = new Map(SCSAIProps.map(p => [p.name, p]));
    
    // 检测新增和修改的属性
    for (const SCSAIProp of SCSAIProps) {
        const localProp = localMap.get(SCSAIProp.name);
        
        if (!localProp) {
            changes.addedProperties.push(SCSAIProp.name);
        } else {
            // 对比属性是否修改
            const propDiff = compareProperty(SCSAIProp, localProp);
            if (propDiff) {
                changes.modifiedProperties.push({
                    name: SCSAIProp.name,
                    changes: propDiff
                });
            }
        }
    }
    
    // 检测删除的属性
    for (const localProp of localProps) {
        if (!SCSAIMap.has(localProp.name)) {
            changes.deletedProperties.push(localProp.name);
        }
    }
    
    // 如果有任何变更,返回详情
    const hasChanges = changes.addedProperties.length > 0 ||
                       changes.modifiedProperties.length > 0 ||
                       changes.deletedProperties.length > 0;
    
    return hasChanges ? changes : null;
}

4.2 增量同步算法

/**
 * 增量同步处理器
 */
async function processSyncQueue(options = {}) {
    const {
        batchSize = 10,
        dryRun = false  // 试运行,不实际执行
    } = options;
    
    // 获取待处理任务
    const tasks = db.prepare(`
        SELECT * FROM sync_queue 
        WHERE status = 'pending' 
        ORDER BY priority ASC, created_at ASC 
        LIMIT ?
    `).all(batchSize);
    
    const results = [];
    
    for (const task of tasks) {
        try {
            // 标记为处理中
            if (!dryRun) {
                db.prepare("UPDATE sync_queue SET status = 'processing', started_at = ? WHERE id = ?")
                  .run(new Date().toISOString(), task.id);
            }
            
            // 执行任务
            let result;
            switch (task.task_type) {
                case 'ITEMTYPE':
                    result = await syncItemType(task);
                    break;
                case 'LIST':
                    result = await syncList(task);
                    break;
                case 'RELATIONSHIP':
                    result = await syncRelationship(task);
                    break;
                case 'PROPERTY':
                    result = await syncProperty(task);
                    break;
            }
            
            // 标记完成
            if (!dryRun) {
                db.prepare(`
                    UPDATE sync_queue 
                    SET status = 'done', completed_at = ?, result_data = ? 
                    WHERE id = ?
                `).run(new Date().toISOString(), JSON.stringify(result), task.id);
            }
            
            results.push({ task, result, success: true });
            
        } catch (error) {
            // 标记失败
            if (!dryRun) {
                db.prepare(`
                    UPDATE sync_queue 
                    SET status = 'failed', error_msg = ?, retry_count = retry_count + 1 
                    WHERE id = ?
                `).run(error.message, task.id);
            }
            
            results.push({ task, error: error.message, success: false });
        }
    }
    
    return results;
}

/**
 * 同步单个 ItemType
 */
async function syncItemType(task) {
    const itemTypeName = task.target_name;
    
    switch (task.task_action) {
        case 'ADD':
            return await importItemTypeFromSCSAI(itemTypeName);
            
        case 'MODIFY':
            // 检测冲突
            const conflict = await detectConflict(itemTypeName);
            if (conflict) {
                // 标记需要审核
                db.prepare(`
                    UPDATE sync_queue 
                    SET needs_review = 1, review_reason = ? 
                    WHERE id = ?
                `).run(JSON.stringify(conflict), task.id);
                return { needsReview: true, conflict };
            }
            return await updateItemTypeFromSCSAI(itemTypeName);
            
        case 'DELETE':
            // 软删除
            return await markItemTypeDeleted(itemTypeName);
    }
}

4.3 冲突检测算法

/**
 * 冲突检测
 * 
 * 场景:SCSAI 修改了 ItemType,但本地管理员也修改了规则模板
 */
async function detectConflict(itemTypeName) {
    // 获取本地修改记录
    const localMods = db.prepare(`
        SELECT * FROM sciot_item_type_versions 
        WHERE item_type_name = ? AND version_source = 'manual' AND status = 'published'
        ORDER BY version DESC LIMIT 1
    `).get(itemTypeName);
    
    if (!localMods) {
        return null; // 无本地修改,无冲突
    }
    
    // 获取上次同步时间
    const syncRecord = db.prepare(`
        SELECT * FROM SCSAI_metadata_versions WHERE item_type_name = ?
    `).get(itemTypeName);
    
    // 如果本地修改时间晚于上次同步时间,可能冲突
    if (localMods.created_at > syncRecord.local_synced_at) {
        // 详细对比
        const SCSAIProps = await fetchSCSAIItemProperties(itemTypeName);
        const localProps = db.prepare(
            'SELECT * FROM sciot_properties WHERE item_type_name = ?'
        ).all(itemTypeName);
        
        const conflicts = findPropertyConflicts(SCSAIProps, localProps);
        
        if (conflicts.length > 0) {
            // 记录冲突
            for (const c of conflicts) {
                db.prepare(`
                    INSERT INTO sync_conflicts 
                    (item_type_name, field_name, conflict_type, SCSAI_value, local_value)
                    VALUES (?, ?, ?, ?, ?)
                `).run(itemTypeName, c.field, c.type, JSON.stringify(c.SCSAI), JSON.stringify(c.local));
            }
            
            return { itemTypeName, conflicts };
        }
    }
    
    return null;
}

5. API 设计

5.1 变更检测 API

POST /api/meta/detect-changes
  请求体: { itemTypes?: string[], forceFullScan?: boolean }
  响应: { changes: Change[], summary: { added, modified, deleted } }

GET /api/meta/sync-status
  响应: { lastSyncTime, pendingTasks, recentChanges }

5.2 同步任务 API

POST /api/meta/sync/start
  请求体: { taskIds?: number[], autoSync?: boolean }
  响应: { taskId, status }

GET /api/meta/sync/queue
  查询参数: { status?: string, limit?: number }
  响应: { tasks: SyncTask[], total }

POST /api/meta/sync/process
  请求体: { batchSize?: number, dryRun?: boolean }
  响应: { results: SyncResult[] }

POST /api/meta/sync/retry/:taskId
  响应: { success, message }

5.3 版本管理 API

GET /api/meta/versions/:itemTypeName
  响应: { versions: Version[], current: Version }

POST /api/meta/versions/publish
  请求体: { itemTypeName: string, version: number }
  响应: { success, publishedVersion }

POST /api/meta/versions/rollback
  请求体: { itemTypeName: string, targetVersion: number }
  响应: { success, currentVersion }

5.4 冲突处理 API

GET /api/meta/conflicts
  查询参数: { resolution?: string }
  响应: { conflicts: Conflict[] }

POST /api/meta/conflicts/:id/resolve
  请求体: { resolution: 'use_SCSAI'|'use_local'|'merge', customValue?: any }
  响应: { success, resolvedValue }

6. 定时任务设计

6.1 任务调度配置

// config/sync-schedule.js
module.exports = {
    // 变更检测
    changeDetection: {
        enabled: true,
        cron: '*/30 * * * *',  // 每 30 分钟
        options: {
            itemTypes: null,      // null = 全部
            forceFullScan: false
        }
    },
    
    // 自动同步
    autoSync: {
        enabled: true,
        cron: '*/5 * * * *',     // 每 5 分钟处理队列
        options: {
            batchSize: 10,
            autoSyncAdd: true,    // 自动同步新增
            autoSyncModify: false, // 修改需要审核
            autoSyncDelete: false  // 删除需要审核
        }
    },
    
    // 版本清理
    versionCleanup: {
        enabled: true,
        cron: '0 2 * * 0',       // 每周日凌晨 2 点
        options: {
            keepVersions: 10,     // 保留最近 10 个版本
            archiveOldVersions: true
        }
    },
    
    // 通知
    notification: {
        onConflict: true,
        onSyncComplete: true,
        onSyncFailure: true,
        channels: ['feishu', 'system']
    }
};

6.2 定时任务实现

// server/services/sync-scheduler.js
const cron = require('node-cron');
const config = require('../config/sync-schedule');

class SyncScheduler {
    constructor() {
        this.jobs = [];
    }
    
    start() {
        // 变更检测任务
        if (config.changeDetection.enabled) {
            const job = cron.schedule(config.changeDetection.cron, async () => {
                console.log('[SyncScheduler] 开始变更检测...');
                try {
                    const result = await detectChanges(config.changeDetection.options);
                    await this.handleDetectionResult(result);
                } catch (e) {
                    console.error('[SyncScheduler] 变更检测失败:', e);
                }
            });
            this.jobs.push(job);
        }
        
        // 自动同步任务
        if (config.autoSync.enabled) {
            const job = cron.schedule(config.autoSync.cron, async () => {
                console.log('[SyncScheduler] 开始处理同步队列...');
                try {
                    const result = await processSyncQueue(config.autoSync.options);
                    await this.handleSyncResult(result);
                } catch (e) {
                    console.error('[SyncScheduler] 同步处理失败:', e);
                }
            });
            this.jobs.push(job);
        }
        
        console.log('[SyncScheduler] 定时任务已启动');
    }
    
    stop() {
        for (const job of this.jobs) {
            job.stop();
        }
        console.log('[SyncScheduler] 定时任务已停止');
    }
    
    async handleDetectionResult(result) {
        // 将变更写入同步队列
        for (const change of result.changes) {
            const priority = change.type === 'DELETE' ? 3 : 
                            change.type === 'ADD' ? 5 : 7;
            
            db.prepare(`
                INSERT INTO sync_queue 
                (task_type, task_action, target_name, priority, task_data)
                VALUES ('ITEMTYPE', ?, ?, ?, ?)
            `).run(change.type, change.item?.name || change.local?.item_type_name, 
                   priority, JSON.stringify(change));
        }
        
        // 发送通知
        if (result.changes.length > 0 && config.notification.onSyncComplete) {
            await sendNotification({
                type: 'changes_detected',
                data: result
            });
        }
    }
}

module.exports = new SyncScheduler();

7. 管理界面设计

7.1 同步状态面板

┌─────────────────────────────────────────────────────────────────┐
│  同步状态                                                        │
├─────────────────────────────────────────────────────────────────┤
│  最后同步: 2026-05-29 14:30:00                                   │
│  待处理任务: 5                                                   │
│  今日变更: 新增 2, 修改 3, 删除 0                                 │
│                                                                  │
│  [立即检测变更]  [处理同步队列]  [查看日志]                        │
└─────────────────────────────────────────────────────────────────┘

7.2 同步队列管理

┌─────────────────────────────────────────────────────────────────┐
│  同步队列                                                        │
├─────────────────────────────────────────────────────────────────┤
│  筛选: [全部] [待处理] [处理中] [已完成] [失败] [需审核]          │
│                                                                  │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │ ⚠️ MODIFY Project (需审核)                                │  │
│  │    原因: 本地规则模板已修改,与 SCSAI 变更冲突               │  │
│  │    [查看详情] [使用SCSAI版本] [保留本地版本] [合并]          │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                  │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │ ✓ ADD NewItemType (待处理)                                │  │
│  │    检测时间: 2026-05-29 14:25:00                           │  │
│  │    [立即同步] [查看详情]                                   │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

7.3 版本历史查看

┌─────────────────────────────────────────────────────────────────┐
│  Part 版本历史                                                   │
├─────────────────────────────────────────────────────────────────┤
│  当前版本: v15 (已发布)                                          │
│                                                                  │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │ v15 (当前) | 2026-05-29 | admin | 已发布                   │  │
│  │    变更: 新增属性 material_grade                           │  │
│  │    [查看详情] [回滚到此版本]                                │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                  │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │ v14 | 2026-05-28 | system | 已发布                         │  │
│  │    变更: 同步 SCSAI 修改                                     │  │
│  │    [查看详情] [回滚到此版本]                                │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

8. 实施计划

8.1 阶段划分

| 阶段 | 任务 | 工作量 | 优先级 | 依赖 |

|------|------|--------|--------|------|

| Phase 1 | 数据库表创建 | 0.5天 | P0 | - |

| Phase 1 | 变更检测算法 | 1天 | P0 | 表创建 |

| Phase 1 | 变更检测 API | 0.5天 | P0 | 算法 |

| Phase 2 | 增量同步引擎 | 1.5天 | P0 | 检测API |

| Phase 2 | 同步任务 API | 0.5天 | P0 | 引擎 |

| Phase 3 | 版本管理机制 | 1天 | P1 | 同步引擎 |

| Phase 3 | 冲突检测算法 | 1天 | P1 | 版本管理 |

| Phase 3 | 冲突处理 API | 0.5天 | P1 | 冲突检测 |

| Phase 4 | 定时任务调度 | 0.5天 | P1 | 同步引擎 |

| Phase 4 | 通知集成 | 0.5天 | P2 | 定时任务 |

| Phase 5 | 管理界面 | 2天 | P2 | 所有API |

| Phase 5 | 文档编写 | 0.5天 | P2 | - |

总工作量: 约 9.5 天

8.2 详细任务分解

#### Phase 1: 基础设施 (2天)

任务 1.1: 创建数据库表

  • 文件: scripts/create-sync-tables.js
  • 内容:
  • 创建 SCSAI_metadata_versions
  • 创建 sync_queue
  • 创建 sync_logs
  • 扩展现有表字段
  • 验证: 表创建成功,索引生效

任务 1.2: 实现变更检测算法

  • 文件: server/services/change-detector.js
  • 函数:
  • detectChanges() - 主入口
  • detectItemModification() - 单项检测
  • compareItemDetails() - 详细对比
  • compareProperty() - 属性对比
  • 验证: 能正确检测新增/修改/删除

任务 1.3: 变更检测 API

  • 文件: server/routes/meta-sync.router.js
  • 端点:
  • POST /api/meta/detect-changes
  • GET /api/meta/sync-status
  • 验证: API 返回正确的变更列表

#### Phase 2: 同步引擎 (2天)

任务 2.1: 增量同步引擎

  • 文件: server/services/incremental-sync.js
  • 函数:
  • processSyncQueue() - 队列处理
  • syncItemType() - ItemType 同步
  • syncList() - List 同步
  • syncRelationship() - Relationship 同步
  • importItemTypeFromSCSAI() - 从 SCSAI 导入
  • updateItemTypeFromSCSAI() - 从 SCSAI 更新
  • markItemTypeDeleted() - 标记删除
  • 验证: 能正确处理各种同步任务

任务 2.2: 同步任务 API

  • 文件: server/routes/meta-sync.router.js
  • 端点:
  • POST /api/meta/sync/start
  • GET /api/meta/sync/queue
  • POST /api/meta/sync/process
  • POST /api/meta/sync/retry/:taskId
  • 验证: API 能正确管理同步任务

#### Phase 3: 版本与冲突 (3天)

任务 3.1: 版本管理机制

  • 文件: server/services/version-manager.js
  • 函数:
  • createVersion() - 创建新版本
  • publishVersion() - 发布版本
  • rollbackVersion() - 回滚版本
  • archiveOldVersions() - 归档旧版本
  • 数据库: 创建 sciot_item_type_versions
  • 验证: 版本创建、发布、回滚正常

任务 3.2: 冲突检测算法

  • 文件: server/services/conflict-detector.js
  • 函数:
  • detectConflict() - 冲突检测
  • findPropertyConflicts() - 属性冲突
  • findRuleConflicts() - 规则冲突
  • 数据库: 创建 sync_conflicts
  • 验证: 能正确检测冲突

任务 3.3: 冲突处理 API

  • 文件: server/routes/meta-sync.router.js
  • 端点:
  • GET /api/meta/conflicts
  • POST /api/meta/conflicts/:id/resolve
  • 验证: 能正确处理冲突

#### Phase 4: 调度与通知 (1天)

任务 4.1: 定时任务调度

  • 文件: server/services/sync-scheduler.js
  • 配置: config/sync-schedule.js
  • 任务:
  • 变更检测定时任务
  • 同步队列处理定时任务
  • 版本清理定时任务
  • 验证: 定时任务正常执行

任务 4.2: 通知集成

  • 文件: server/services/sync-notifier.js
  • 通道:
  • 飞书通知
  • 系统内通知
  • 事件:
  • 变更检测完成
  • 同步完成
  • 同步失败
  • 冲突需要审核
  • 验证: 通知正常发送

#### Phase 5: 界面与文档 (2.5天)

任务 5.1: 同步状态面板

  • 文件: src/views/MetaSync.vue (新建)
  • 组件:
  • 同步状态概览
  • 快捷操作按钮
  • 最近变更列表
  • 验证: 界面正常显示

任务 5.2: 同步队列管理

  • 文件: src/views/MetaSync.vue
  • 组件:
  • 任务列表
  • 任务筛选
  • 任务详情
  • 审核操作
  • 验证: 能管理同步任务

任务 5.3: 版本历史查看

  • 文件: src/views/MetaSync.vue
  • 组件:
  • 版本列表
  • 版本详情
  • 回滚操作
  • 验证: 能查看和管理版本

任务 5.4: 文档编写

  • 文件: docs/meta-sync-system.md
  • 内容:
  • 系统架构说明
  • API 文档
  • 使用指南
  • 故障排查

9. 风险与缓解

风险影响概率缓解措施
SCSAI API 不稳定同步失败重试机制、降级为手动同步
大量变更同时发生队列积压批量处理、优先级队列
冲突频繁发生需大量人工审核智能合并策略、自动解决简单冲突
版本数据膨胀存储压力定期归档、压缩旧版本
定时任务冲突数据不一致分布式锁、任务互斥

10. 验收标准

10.1 功能验收

  • [ ] 能检测 SCSAI 新增的 ItemType 并自动同步
  • [ ] 能检测 SCSAI 修改的属性并生成同步任务
  • [ ] 能检测 SCSAI 删除的 ItemType 并标记删除
  • [ ] 能检测 List 值变更并更新可选值列表
  • [ ] 能检测本地修改与 SCSAI 变更的冲突
  • [ ] 能通过管理界面审核冲突
  • [ ] 能查看版本历史并回滚
  • [ ] 定时任务正常执行
  • [ ] 通知正常发送

10.2 性能验收

  • [ ] 变更检测响应时间 < 30秒
  • [ ] 单个 ItemType 同步时间 < 5秒
  • [ ] 批量同步 100 个任务 < 5分钟
  • [ ] 版本回滚时间 < 10秒

10.3 可靠性验收

  • [ ] 同步失败后能自动重试
  • [ ] 重试 3 次后标记失败
  • [ ] 冲突不会导致数据丢失
  • [ ] 版本回滚能恢复到正确状态

附录 A: 配置文件示例

// config/sync-config.js
module.exports = {
    // SCSAI 连接
    SCSAI: {
        serverUrl: 'https://ylxt.chat/scplm',
        database: 'SCPLM',
        timeout: 30000
    },
    
    // 变更检测
    detection: {
        enabled: true,
        mode: 'scheduled',        // scheduled | webhook | manual
        cron: '*/30 * * * *',
        webhookSecret: 'xxx'
    },
    
    // 同步策略
    sync: {
        autoSyncAdd: true,
        autoSyncModify: false,
        autoSyncDelete: false,
        batchSize: 10,
        maxRetry: 3,
        retryDelay: 5000
    },
    
    // 版本管理
    version: {
        keepVersions: 10,
        autoArchive: true,
        archiveAfterDays: 30
    },
    
    // 通知
    notification: {
        enabled: true,
        channels: ['feishu', 'system'],
        feishu: {
            webhook: 'https://open.feishu.cn/xxx',
            secret: 'xxx'
        },
        onConflict: true,
        onSyncComplete: true,
        onSyncFailure: true
    }
};

附录 B: 错误码定义

| 错误码 | 含义 | 处理建议 |

|--------|------|----------|

| SYNC_001 | SCSAI 连接失败 | 检查网络和配置 |

| SYNC_002 | SCSAI 认证失败 | 检查用户名密码 |

| SYNC_003 | 元数据解析失败 | 检查 SCSAI 版本兼容性 |

| SYNC_004 | 本地数据库写入失败 | 检查磁盘空间和权限 |

| SYNC_005 | 冲突检测失败 | 检查版本记录完整性 |

| SYNC_006 | 版本回滚失败 | 检查目标版本是否存在 |

| SYNC_007 | 通知发送失败 | 检查通知配置 |

← 返回案例列表
分享:
🤖 Try Now →
🤖
🎁