feat(evaluation): 模块1.4 - 新增评查点分组批量操作接口
## 主要改进 ### 1. 新增 batchUpdateRuleGroupStatus 函数(批量启用/禁用) - ✅ 参数验证(ID列表不为空,每个ID有效) - ✅ 逐个验证分组存在性 - ✅ 逐个执行更新操作 - ✅ 返回详细的操作结果 - updated_count: 成功更新的数量 - failed_ids: 失败的ID列表 - errors: 详细的错误信息(包含ID和错误原因) ### 2. 新增 batchDeleteRuleGroups 函数(批量删除) - ✅ 参数验证(ID列表不为空,每个ID有效) - ✅ 采用安全的阻止删除策略 - ✅ 逐个检查并删除分组 - ✅ 返回详细的操作结果和错误信息 - deleted_count: 成功删除的数量 - failed_ids: 失败的ID列表 - errors: 详细的错误信息(包含子分组/评查点检查结果) ### 3. 批量操作特性 - ✅ **逐个处理**:确保每个分组都能被正确处理 - ✅ **部分成功支持**:即使部分分组操作失败,成功的也会被处理 - ✅ **详细的错误追踪**:记录每个失败的ID及其失败原因 - ✅ **安全性优先**:批量删除继承单个删除的安全检查 ### 4. 返回值结构 ```typescript // 批量更新状态 { success: boolean; // 是否全部成功 updated_count: number; // 成功更新的数量 failed_ids: string[]; // 失败的ID列表 errors?: Array<{ // 详细错误(可选) id: string; error: string; }>; } // 批量删除 { success: boolean; // 是否全部成功 deleted_count: number; // 成功删除的数量 failed_ids: string[]; // 失败的ID列表 errors?: Array<{ // 详细错误(可选) id: string; error: string; details?: { // 删除失败详情 hasChildren?: boolean; hasPoints?: boolean; }; }>; } ``` ## 使用示例 ### 批量启用分组 ```typescript const result = await batchUpdateRuleGroupStatus( ['1', '2', '3'], true, token ); if (result.success) { console.log(`成功启用 ${result.updated_count} 个分组`); } else { console.log(`成功 ${result.updated_count} 个,失败 ${result.failed_ids.length} 个`); result.errors?.forEach(err => { console.log(`分组 ${err.id}: ${err.error}`); }); } ``` ### 批量删除分组 ```typescript const result = await batchDeleteRuleGroups(['1', '2'], token); if (result.success) { console.log(`成功删除 ${result.deleted_count} 个分组`); } else { result.errors?.forEach(err => { if (err.details?.hasChildren) { console.log(`分组 ${err.id} 有子分组,无法删除`); } if (err.details?.hasPoints) { console.log(`分组 ${err.id} 有评查点,无法删除`); } }); } ``` ## 相关文件 - app/api/evaluation_points/rule-groups.ts ## 验收清单 - [x] TypeScript 类型检查通过 - [x] 完整的参数验证 - [x] 支持部分成功场景 - [x] 详细的错误追踪 - [x] 安全的删除策略 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -937,9 +937,204 @@ async function deleteEvaluationPointsByGroupId(groupId: string, token?: string):
|
|||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('删除评查点失败:', error);
|
console.error('删除评查点失败:', error);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: error instanceof Error ? error.message : '删除评查点失败'
|
error: error instanceof Error ? error.message : '删除评查点失败'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 批量操作接口 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量更新分组状态(启用/禁用)
|
||||||
|
* @param ids 分组ID列表
|
||||||
|
* @param is_enabled 目标状态
|
||||||
|
* @param token JWT token (可选)
|
||||||
|
* @returns 更新结果
|
||||||
|
*/
|
||||||
|
export async function batchUpdateRuleGroupStatus(
|
||||||
|
ids: string[],
|
||||||
|
is_enabled: boolean,
|
||||||
|
token?: string
|
||||||
|
): Promise<{
|
||||||
|
success: boolean;
|
||||||
|
updated_count: number;
|
||||||
|
failed_ids: string[];
|
||||||
|
errors?: Array<{ id: string; error: string }>;
|
||||||
|
}> {
|
||||||
|
try {
|
||||||
|
// ========== 1. 参数验证 ==========
|
||||||
|
|
||||||
|
if (!Array.isArray(ids) || ids.length === 0) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
updated_count: 0,
|
||||||
|
failed_ids: [],
|
||||||
|
errors: [{ id: 'validation', error: 'ID列表不能为空' }]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证每个ID的有效性
|
||||||
|
const invalidIds = ids.filter(id => !id || id.trim() === '');
|
||||||
|
if (invalidIds.length > 0) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
updated_count: 0,
|
||||||
|
failed_ids: ids,
|
||||||
|
errors: [{ id: 'validation', error: '存在无效的分组ID' }]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 2. 逐个更新(确保每个分组都能被正确处理) ==========
|
||||||
|
|
||||||
|
const failedIds: string[] = [];
|
||||||
|
const errors: Array<{ id: string; error: string }> = [];
|
||||||
|
let updatedCount = 0;
|
||||||
|
|
||||||
|
for (const id of ids) {
|
||||||
|
try {
|
||||||
|
// 验证分组是否存在
|
||||||
|
const groupResponse = await getRuleGroup(id, token);
|
||||||
|
if (groupResponse.error || !groupResponse.data) {
|
||||||
|
failedIds.push(id);
|
||||||
|
errors.push({ id, error: '分组不存在或无法访问' });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行更新
|
||||||
|
const updateResponse = await postgrestPut<ApiResponse<RuleGroup> | RuleGroup, Partial<ApiRuleGroup>>(
|
||||||
|
'evaluation_point_groups',
|
||||||
|
{ is_enabled },
|
||||||
|
{ id },
|
||||||
|
token
|
||||||
|
);
|
||||||
|
|
||||||
|
if (updateResponse.error) {
|
||||||
|
failedIds.push(id);
|
||||||
|
errors.push({ id, error: updateResponse.error });
|
||||||
|
} else {
|
||||||
|
updatedCount++;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
failedIds.push(id);
|
||||||
|
errors.push({
|
||||||
|
id,
|
||||||
|
error: error instanceof Error ? error.message : '更新失败'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 3. 返回结果 ==========
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: failedIds.length === 0,
|
||||||
|
updated_count: updatedCount,
|
||||||
|
failed_ids: failedIds,
|
||||||
|
errors: errors.length > 0 ? errors : undefined
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('批量更新分组状态失败:', error);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
updated_count: 0,
|
||||||
|
failed_ids: ids,
|
||||||
|
errors: [{
|
||||||
|
id: 'batch',
|
||||||
|
error: error instanceof Error ? error.message : '批量更新失败'
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除分组(安全的阻止删除策略)
|
||||||
|
* @param ids 分组ID列表
|
||||||
|
* @param token JWT token (可选)
|
||||||
|
* @returns 删除结果
|
||||||
|
*/
|
||||||
|
export async function batchDeleteRuleGroups(
|
||||||
|
ids: string[],
|
||||||
|
token?: string
|
||||||
|
): Promise<{
|
||||||
|
success: boolean;
|
||||||
|
deleted_count: number;
|
||||||
|
failed_ids: string[];
|
||||||
|
errors?: Array<{ id: string; error: string; details?: { hasChildren?: boolean; hasPoints?: boolean } }>;
|
||||||
|
}> {
|
||||||
|
try {
|
||||||
|
// ========== 1. 参数验证 ==========
|
||||||
|
|
||||||
|
if (!Array.isArray(ids) || ids.length === 0) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
deleted_count: 0,
|
||||||
|
failed_ids: [],
|
||||||
|
errors: [{ id: 'validation', error: 'ID列表不能为空' }]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证每个ID的有效性
|
||||||
|
const invalidIds = ids.filter(id => !id || id.trim() === '');
|
||||||
|
if (invalidIds.length > 0) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
deleted_count: 0,
|
||||||
|
failed_ids: ids,
|
||||||
|
errors: [{ id: 'validation', error: '存在无效的分组ID' }]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 2. 逐个删除(使用安全的阻止删除策略) ==========
|
||||||
|
|
||||||
|
const failedIds: string[] = [];
|
||||||
|
const errors: Array<{ id: string; error: string; details?: { hasChildren?: boolean; hasPoints?: boolean } }> = [];
|
||||||
|
let deletedCount = 0;
|
||||||
|
|
||||||
|
for (const id of ids) {
|
||||||
|
try {
|
||||||
|
const deleteResult = await deleteRuleGroup(id, token);
|
||||||
|
|
||||||
|
if (!deleteResult.success) {
|
||||||
|
failedIds.push(id);
|
||||||
|
errors.push({
|
||||||
|
id,
|
||||||
|
error: deleteResult.error || '删除失败',
|
||||||
|
details: deleteResult.details ? {
|
||||||
|
hasChildren: deleteResult.details.hasChildren,
|
||||||
|
hasPoints: deleteResult.details.hasPoints
|
||||||
|
} : undefined
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
deletedCount++;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
failedIds.push(id);
|
||||||
|
errors.push({
|
||||||
|
id,
|
||||||
|
error: error instanceof Error ? error.message : '删除失败'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 3. 返回结果 ==========
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: failedIds.length === 0,
|
||||||
|
deleted_count: deletedCount,
|
||||||
|
failed_ids: failedIds,
|
||||||
|
errors: errors.length > 0 ? errors : undefined
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('批量删除分组失败:', error);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
deleted_count: 0,
|
||||||
|
failed_ids: ids,
|
||||||
|
errors: [{
|
||||||
|
id: 'batch',
|
||||||
|
error: error instanceof Error ? error.message : '批量删除失败'
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user