{"record":{"id":"432f3aabc5ce5f44","repo":"flipped-aurora/gin-vue-admin","slug":"error-432f3a","errorCode":null,"errorMessage":"该字典详情下还有子项，无法删除","messagePattern":"该字典详情下还有子项，无法删除","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/service/system/sys_dictionary_detail.go","lineNumber":60,"sourceCode":"\terr = global.GVA_DB.WithContext(ctx).Create(&sysDictionaryDetail).Error\n\treturn err\n}\n\n//@author: [piexlmax](https://github.com/piexlmax)\n//@function: DeleteSysDictionaryDetail\n//@description: 删除字典详情数据\n//@param: sysDictionaryDetail model.SysDictionaryDetail\n//@return: err error\n\nfunc (dictionaryDetailService *DictionaryDetailService) DeleteSysDictionaryDetail(ctx context.Context, sysDictionaryDetail system.SysDictionaryDetail) (err error) {\n\t// 检查是否有子项\n\tvar count int64\n\terr = global.GVA_DB.WithContext(ctx).Model(&system.SysDictionaryDetail{}).Where(\"parent_id = ?\", sysDictionaryDetail.ID).Count(&count).Error\n\tif err != nil {\n\t\treturn err\n\t}\n\tif count > 0 {\n\t\treturn fmt.Errorf(\"该字典详情下还有子项，无法删除\")\n\t}\n\n\terr = global.GVA_DB.WithContext(ctx).Delete(&sysDictionaryDetail).Error\n\treturn err\n}\n\n//@author: [piexlmax](https://github.com/piexlmax)\n//@function: UpdateSysDictionaryDetail\n//@description: 更新字典详情数据\n//@param: sysDictionaryDetail *model.SysDictionaryDetail\n//@return: err error\n\nfunc (dictionaryDetailService *DictionaryDetailService) UpdateSysDictionaryDetail(ctx context.Context, sysDictionaryDetail *system.SysDictionaryDetail) (err error) {\n\t// 如果更新了父级ID，需要重新计算层级和路径\n\tif sysDictionaryDetail.ParentID != nil {\n\t\tvar parent system.SysDictionaryDetail\n\t\terr = global.GVA_DB.WithContext(ctx).First(&parent, *sysDictionaryDetail.ParentID).Error\n\t\tif err != nil {","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/sys_dictionary_detail.go#L42-L78","documentation":"DeleteSysDictionaryDetail refuses to delete a dictionary detail that still has child items. Before deleting, it counts rows in sys_dictionary_detail where parent_id equals the target's ID; if any exist it returns this error instead of performing the delete, preventing orphaned children.","triggerScenarios":"Calling DeleteSysDictionaryDetail (or the DELETE /sysDictionaryDetail/deleteSysDictionaryDetail API) with the ID of a detail that has children whose parent_id points at it.","commonSituations":"Users delete a parent dictionary entry in the admin UI while its sub-items still exist; hierarchical dictionaries built via parent_id where leaves were created before the parent was removed; import/seed data with nested details.","solutions":["Delete or re-parent the child details first, then delete the parent","Query children with parent_id = <id> and delete them recursively before deleting","If children are not wanted, set their parent_id to the parent's parent or NULL before deleting"],"exampleFix":"// before\nawait deleteDictionaryDetail({ id: parentId }) // fails when children exist\n// after\nconst children = await getDetails({ parentId })\nfor (const c of children) {\n  await deleteDictionaryDetail({ id: c.id })\n}\nawait deleteDictionaryDetail({ id: parentId })","handlingStrategy":"validation","validationCode":"const { data } = await getDetailChildren(id)\nif (data > 0) throw new Error('delete children first')","typeGuard":null,"tryCatchPattern":"try {\n  await deleteDetail(id)\n} catch (e) {\n  if (e.message.includes('子项')) {\n    ElMessage.warning('请先删除子项')\n  }\n}","preventionTips":["Show children count on delete confirmation dialogs","Offer cascade delete with explicit confirmation"],"tags":["go","gorm","dictionary","business-rule"],"backgroundTag":"delete-blocked-by-children","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}