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-changesGET /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/startGET /api/meta/sync/queuePOST /api/meta/sync/processPOST /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/conflictsPOST /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 | 通知发送失败 | 检查通知配置 |
BossAgents