fix: 修复插件保存后的分类关联

- 插件保存接口返回实体以便前端拿到真实插件 ID

- 分类关联更新改为按差异增删并补充事务保护

- 新建插件后缺失 ID 时明确抛出错误
This commit is contained in:
2026-03-24 18:38:09 +08:00
parent 6e1bd73cd8
commit 799174406e
6 changed files with 49 additions and 46 deletions

View File

@@ -40,7 +40,7 @@ public class PluginController extends BaseCurdController<PluginService, Plugin>
@PostMapping("/plugin/save")
@SaCheckPermission("/api/v1/plugin/save")
public Result<Boolean> savePlugin(@JsonBody Plugin plugin){
public Result<Plugin> savePlugin(@JsonBody Plugin plugin){
return Result.ok(pluginService.savePlugin(plugin));
}

View File

@@ -5,7 +5,6 @@ import tech.easyflow.ai.entity.PluginCategory;
import tech.easyflow.ai.entity.PluginCategoryMapping;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
/**
@@ -16,7 +15,7 @@ import java.util.List;
*/
public interface PluginCategoryMappingService extends IService<PluginCategoryMapping> {
boolean updateRelation(BigInteger pluginId, ArrayList<BigInteger> categoryIds);
boolean updateRelation(BigInteger pluginId, List<BigInteger> categoryIds);
List<PluginCategory> getPluginCategories(BigInteger pluginId);
}

View File

@@ -14,7 +14,7 @@ import java.util.List;
*/
public interface PluginService extends IService<Plugin> {
boolean savePlugin(Plugin plugin);
Plugin savePlugin(Plugin plugin);
boolean removePlugin(String id);

View File

@@ -2,18 +2,23 @@ package tech.easyflow.ai.service.impl;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.easyflow.ai.entity.PluginCategory;
import tech.easyflow.ai.entity.PluginCategoryMapping;
import tech.easyflow.ai.mapper.PluginCategoryMapper;
import tech.easyflow.ai.mapper.PluginCategoryMappingMapper;
import tech.easyflow.ai.service.PluginCategoryMappingService;
import org.springframework.stereotype.Service;
import tech.easyflow.common.web.exceptions.BusinessException;
import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 服务层实现。
@@ -31,45 +36,46 @@ public class PluginCategoryMappingServiceImpl extends ServiceImpl<PluginCategory
private PluginCategoryMapper pluginCategoryMapper;
@Override
public boolean updateRelation(BigInteger pluginId, ArrayList<BigInteger> categoryIds) {
if (categoryIds == null){
QueryWrapper queryWrapper = QueryWrapper.create().select("*")
.from("tb_plugin_category_mapping")
.where("plugin_id = ?", pluginId);
int delete = relationMapper.deleteByQuery(queryWrapper);
if (delete <= 0){
throw new BusinessException("删除失败");
}
return true;
@Transactional
public boolean updateRelation(BigInteger pluginId, List<BigInteger> categoryIds) {
if (pluginId == null) {
throw new BusinessException("插件ID不能为空");
}
for (BigInteger categoryId : categoryIds) {
QueryWrapper queryWrapper = QueryWrapper.create().select("*")
List<BigInteger> targetCategoryIds = categoryIds == null
? Collections.emptyList()
: categoryIds.stream()
.filter(java.util.Objects::nonNull)
.distinct()
.collect(Collectors.toList());
QueryWrapper currentRelationQuery = QueryWrapper.create().select("category_id")
.from("tb_plugin_category_mapping")
.where("plugin_id = ?", pluginId);
List<BigInteger> currentCategoryIds = relationMapper.selectListByQueryAs(currentRelationQuery, BigInteger.class);
Set<BigInteger> currentCategoryIdSet = new LinkedHashSet<>(currentCategoryIds);
Set<BigInteger> targetCategoryIdSet = new LinkedHashSet<>(targetCategoryIds);
Set<BigInteger> categoryIdsToDelete = new LinkedHashSet<>(currentCategoryIdSet);
categoryIdsToDelete.removeAll(targetCategoryIdSet);
if (!categoryIdsToDelete.isEmpty()) {
QueryWrapper deleteQuery = QueryWrapper.create()
.from("tb_plugin_category_mapping")
.where("plugin_id = ?", pluginId)
.where("category_id = ?", categoryId);
PluginCategoryMapping selectedOneByQuery = relationMapper.selectOneByQuery(queryWrapper);
.where("plugin_id = ?", pluginId)
.in("category_id", new ArrayList<>(categoryIdsToDelete));
relationMapper.deleteByQuery(deleteQuery);
}
Set<BigInteger> categoryIdsToInsert = new LinkedHashSet<>(targetCategoryIdSet);
categoryIdsToInsert.removeAll(currentCategoryIdSet);
for (BigInteger categoryId : categoryIdsToInsert) {
PluginCategoryMapping pluginCategoryMapping = new PluginCategoryMapping();
pluginCategoryMapping.setCategoryId(categoryId);
pluginCategoryMapping.setPluginId(pluginId);
if (selectedOneByQuery == null) {
int insert = relationMapper.insert(pluginCategoryMapping);
if (insert <= 0) {
throw new BusinessException("新增失败");
}
} else {
QueryWrapper queryWrapperUpdate = QueryWrapper.create().select("*")
.from("tb_plugin_category_mapping")
.where("plugin_id = ?", pluginId);
PluginCategoryMapping selectedOne = relationMapper.selectOneByQuery(queryWrapper);
if (selectedOne != null){
continue;
}
int update = relationMapper.updateByQuery(pluginCategoryMapping, queryWrapperUpdate);
if (update <= 0){
throw new BusinessException("更新失败");
}
int insert = relationMapper.insert(pluginCategoryMapping);
if (insert <= 0) {
throw new BusinessException("新增分类关联失败");
}
}
return true;
}

View File

@@ -48,13 +48,13 @@ public class PluginServiceImpl extends ServiceImpl<PluginMapper, Plugin> impleme
private PluginItemService pluginItemService;
@Override
public boolean savePlugin(Plugin plugin) {
public Plugin savePlugin(Plugin plugin) {
plugin.setCreated(new Date());
int insert = pluginMapper.insert(plugin);
if (insert <= 0) {
throw new BusinessException("保存失败");
}
return true;
return plugin;
}
@Override

View File

@@ -145,12 +145,10 @@ function save() {
})
.then(async (res) => {
if (res.errorCode === 0) {
const pluginId =
res.data?.id ||
res.data ||
plainEntity.id ||
entity.value.id ||
'';
const pluginId = res.data?.id || plainEntity.id || entity.value.id;
if (!pluginId) {
throw new Error('插件保存成功但未返回插件ID');
}
await syncPluginCategories(pluginId, categoryIds);
dialogVisible.value = false;
ElMessage.success($t('message.saveOkMessage'));