@ -16,8 +16,11 @@ import com.huoran.iasf.mapper.SysFloatingColumnSchemeMapper;
import com.huoran.iasf.mapper.SysFloatingColumnSchemeModuleMapper ;
import com.huoran.iasf.mapper.SysFloatingColumnSchemeScopeOfApplicationMapper ;
import com.huoran.iasf.service.SysFloatingColumnSchemeService ;
import com.huoran.iasf.vo.ConflictCheckResultVO ;
import com.huoran.iasf.vo.SysFloatingColumnSchemeScopeOfApplicationWithSiteIdVO ;
import com.huoran.iasf.vo.SysFloatingColumnSchemeVO ;
import com.huoran.iasf.vo.req.SuspensionBarListPagingReq ;
import org.apache.commons.lang3.math.NumberUtils ;
import org.apache.commons.logging.Log ;
import org.apache.commons.logging.LogFactory ;
import org.springframework.beans.factory.annotation.Autowired ;
@ -205,94 +208,129 @@ public class SysFloatingColumnSchemeServiceImpl extends ServiceImpl<SysFloatingC
//查询当前站点下已启用,且已发布的悬浮栏
List < SysFloatingColumnScheme > floatingColumnSchemeList = baseMapper . selectList ( new LambdaQueryWrapper < SysFloatingColumnScheme > ( )
. eq ( SysFloatingColumnScheme : : getSiteId , column . getSiteId ( ) )
. eq ( SysFloatingColumnScheme : : getIsDisable , 0 )
. eq ( SysFloatingColumnScheme : : getStatus , 1 ) ) ;
List < SysFloatingColumnScheme > floatingColumnSchemeList = baseMapper . selectList ( new LambdaQueryWrapper < SysFloatingColumnScheme > ( ) . eq ( SysFloatingColumnScheme : : getSiteId , column . getSiteId ( ) ) . eq ( SysFloatingColumnScheme : : getIsDisable , 0 ) . eq ( SysFloatingColumnScheme : : getStatus , 1 ) ) ;
for ( SysFloatingColumnScheme scheme : floatingColumnSchemeList ) {
//判断当前启用的栏目如果为全局的直接返回全局的已启用的方案
if ( scheme . getIsGlobal ( ) = = 1 ) {
//查询悬浮栏当前绑定的方案
List < SysFloatingColumnSchemeModule > columnSchemeModule = floatingColumnSchemeModuleMapper . selectList ( new LambdaQueryWrapper < SysFloatingColumnSchemeModule > ( )
. eq ( SysFloatingColumnSchemeModule : : getFloatingBarSchemeId , scheme . getId ( ) ) . eq ( SysFloatingColumnSchemeModule : : getIsDisable , 0 ) ) ;
List < SysFloatingColumnSchemeModule > columnSchemeModule = floatingColumnSchemeModuleMapper . selectList ( new LambdaQueryWrapper < SysFloatingColumnSchemeModule > ( ) . eq ( SysFloatingColumnSchemeModule : : getFloatingBarSchemeId , scheme . getId ( ) ) . eq ( SysFloatingColumnSchemeModule : : getIsDisable , 0 ) ) ;
;
if ( ! ObjectUtil . isEmpty ( columnSchemeModule ) ) {
return R . success ( columnSchemeModule ) ;
}
} else {
} else {
//查询栏目绑定过的悬浮栏
List < Integer > floatingBarIds = scopeOfApplicationMapper . checkBoundByColumnId ( columnId ) ;
//查询悬浮栏绑定的方案
for ( Integer floatingBarId : floatingBarIds ) {
List < SysFloatingColumnSchemeModule > list = floatingColumnSchemeModuleMapper . selectList ( new LambdaQueryWrapper < SysFloatingColumnSchemeModule > ( )
. eq ( SysFloatingColumnSchemeModule : : getFloatingBarSchemeId , floatingBarId ) . eq ( SysFloatingColumnSchemeModule : : getIsDisable , 0 ) ) ;
for ( Integer floatingBarId : floatingBarIds ) {
List < SysFloatingColumnSchemeModule > list = floatingColumnSchemeModuleMapper . selectList ( new LambdaQueryWrapper < SysFloatingColumnSchemeModule > ( ) . eq ( SysFloatingColumnSchemeModule : : getFloatingBarSchemeId , floatingBarId ) . eq ( SysFloatingColumnSchemeModule : : getIsDisable , 0 ) ) ;
columnSchemeModuleList . addAll ( list ) ;
}
return R . success ( columnSchemeModuleList ) ;
}
}
return R . success ( columnSchemeModuleList ) ;
}
/ * @Override
public R columnDisplayFloatingBar ( String columnId ) {
//获取站点
SysColumn column = columnMapper . selectById ( columnId ) ;
if ( ObjectUtil . isEmpty ( column ) ) {
return R . fail ( "未找到该栏目" ) ;
}
//查询范围应用为栏目的
* //* List<SysFloatingColumnSchemeScopeOfApplication> sysFloatingColumnSchemeScopeOfApplications = scopeOfApplicationMapper.selectList(new LambdaQueryWrapper<SysFloatingColumnSchemeScopeOfApplication>()
. eq ( SysFloatingColumnSchemeScopeOfApplication : : getFloatingBarSchemeId , columnId )
) ;
* //*
//查询栏目绑定过的悬浮栏
List < Integer > sysFloatingColumnSchemeScopeOfApplications = scopeOfApplicationMapper . checkBoundByColumnId ( columnId ) ;
List < SysFloatingColumnSchemeModule > columnSchemeModuleList = new ArrayList < > ( ) ;
/ * *
* 在多个悬浮栏方案更新前 , 预先检查是否存在应用范围冲突 。
*
* @param siteId 当前操作所在的站点ID 。
* @param updatedScopes 待更新的悬浮栏方案列表 。
* @return 冲突检测结果 , 包含是否有冲突及详细的冲突信息 。
* /
@Transactional ( readOnly = true )
public ConflictCheckResultVO preCheckMultiScopeConflictBeforeUpdate (
Integer siteId , List < SysFloatingColumnSchemeScopeOfApplication > updatedScopes , Integer floatingBarSchemeId ) {
for ( Integer floatingBarId : sysFloatingColumnSchemeScopeOfApplications ) {
//查询启用的悬浮栏
SysFloatingColumnScheme scheme = floatingColumnSchemeMapper . selectById ( floatingBarId ) ;
// 1. 收集待更新方案的ID,用于排除这些方案在冲突检测中的干扰
List < String > excludeSchemeIds = updatedScopes . stream ( )
. map ( SysFloatingColumnSchemeScopeOfApplication : : getApplicationScopeId )
. collect ( Collectors . toList ( ) ) ;
if ( ! ObjectUtil . isEmpty ( scheme ) ) {
//且为启用状态下才查询绑定的方案
if ( scheme . getIsDisable ( ) = = 0 ) {
//查询悬浮栏当前绑定的方案
List < SysFloatingColumnSchemeModule > columnSchemeModule = floatingColumnSchemeModuleMapper . selectList ( new LambdaQueryWrapper < SysFloatingColumnSchemeModule > ( )
. eq ( SysFloatingColumnSchemeModule : : getFloatingBarSchemeId , scheme . getId ( ) ) . eq ( SysFloatingColumnSchemeModule : : getIsDisable , 0 ) ) ; ;
if ( ! ObjectUtil . isEmpty ( columnSchemeModule ) ) {
columnSchemeModuleList . addAll ( columnSchemeModule ) ;
// 2. 从数据库查询该站点下所有启用的悬浮栏方案,但排除掉当前正在更新的那些方案
List < SysFloatingColumnSchemeScopeOfApplicationWithSiteIdVO > enabledScopes =
baseMapper . selectEnabledScopesForMultiConflictCheck ( siteId , excludeSchemeIds , floatingBarSchemeId ) ;
/ * // 初始化冲突标记为false,并准备一个StringBuilder用于记录冲突信息
boolean hasConflict = false ;
StringBuilder conflictMessage = new StringBuilder ( ) ;
// 3. 对比每个待更新的方案与已启用方案,检测应用范围是否有重叠
for ( SysFloatingColumnSchemeScopeOfApplicationWithSiteIdVO existingScope : enabledScopes ) {
for ( SysFloatingColumnSchemeScopeOfApplication newScope : updatedScopes ) {
// 假设冲突基于应用范围的直接比较,实际情况可能需要更复杂的逻辑
if ( existingScope . getApplicationScopeId ( ) . equals ( newScope . getApplicationScopeId ( ) ) ) {
hasConflict = true ;
conflictMessage . append ( "发现冲突:方案“" )
. append ( existingScope . getSchemeName ( ) )
. append ( "”与待更新的方案在应用范围“" )
. append ( newScope . getApplicationScopeId ( ) )
. append ( "”上重叠。\n" ) ;
}
}
} * /
// 初始化冲突标记为false,并准备一个StringBuilder用于记录冲突信息
boolean hasConflict = false ;
StringBuilder conflictMessageBuilder = new StringBuilder ( ) ;
Set < String > conflictColumnNames = new HashSet < > ( ) ; // 用于存储所有冲突的栏目名称
// 3. 对比每个待更新的方案与已启用方案,检测应用范围是否有重叠
for ( SysFloatingColumnSchemeScopeOfApplicationWithSiteIdVO existingScope : enabledScopes ) {
for ( SysFloatingColumnSchemeScopeOfApplication newScope : updatedScopes ) {
// 分割应用范围ID为集合,以便逐个比较
Set < Integer > existingScopeIds = Arrays . stream ( existingScope . getApplicationScopeId ( ) . split ( "," ) )
. map ( String : : trim )
. filter ( id - > ! id . isEmpty ( ) & & NumberUtils . isCreatable ( id ) )
. map ( Integer : : parseInt )
. collect ( Collectors . toSet ( ) ) ;
Set < Integer > newScopeIds = Arrays . stream ( newScope . getApplicationScopeId ( ) . split ( "," ) )
. map ( String : : trim )
. filter ( id - > ! id . isEmpty ( ) & & NumberUtils . isCreatable ( id ) )
. map ( Integer : : parseInt )
. collect ( Collectors . toSet ( ) ) ;
// 找出重叠的范围ID
Set < Integer > overlapIds = new HashSet < > ( existingScopeIds ) ;
overlapIds . retainAll ( newScopeIds ) ;
// 避免重复处理相同的冲突范围
if ( ! overlapIds . isEmpty ( ) ) {
for ( Integer overlapId : overlapIds ) {
String columnName = getColumnNameById ( String . valueOf ( overlapId ) ) ; // 假设这是获取栏目名称的方法
conflictColumnNames . add ( columnName ) ; // 收集冲突的栏目名称
}
}
}
}
// 构建最终的冲突信息,如果存在冲突
if ( ! conflictColumnNames . isEmpty ( ) ) {
hasConflict = true ;
conflictMessageBuilder . append ( "栏目:" ) ;
boolean isFirst = true ;
for ( String columnName : conflictColumnNames ) {
if ( ! isFirst ) {
conflictMessageBuilder . append ( "、" ) ; // 使用中文逗号作为分隔符
}
conflictMessageBuilder . append ( columnName ) ;
isFirst = false ;
}
conflictMessageBuilder . append ( " 已设置有悬浮栏,请先移除相关设置再尝试启用。\n" ) ;
}
// 4. 根据检测结果创建并返回ConflictCheckResult对象
return new ConflictCheckResultVO ( hasConflict , conflictMessageBuilder . toString ( ) ) ;
}
return R . success ( columnSchemeModuleList ) ;
} * /
// 辅助方法检查站点下是否存在启用的全局悬浮栏
private boolean existsEnabledGlobal ( Integer siteId ) {
@ -333,6 +371,7 @@ public class SysFloatingColumnSchemeServiceImpl extends ServiceImpl<SysFloatingC
Set < Integer > enabledScopeIds = Arrays . stream ( enabledScope . getApplicationScopeId ( ) . split ( "," ) ) . map ( Integer : : parseInt ) . collect ( Collectors . toSet ( ) ) ;
if ( ! Collections . disjoint ( currentScopeIds , enabledScopeIds ) ) {
// System.err.println("--------------->>>>重叠的范围ID: " + currentScopeIds.stream());
return true ; // 存在重叠
}
}
@ -346,51 +385,56 @@ public class SysFloatingColumnSchemeServiceImpl extends ServiceImpl<SysFloatingC
* @param schemeId 悬浮栏方案ID
* @return 冲突提示信息
* /
/ * *
* 生成关于悬浮栏方案范围冲突的提示信息 。
* 只有当尝试启用的悬浮栏方案与现有启用的方案存在范围重叠时 , 才会生成冲突信息 。
*
* @param schemeId 当前操作的悬浮栏方案ID 。
* @param siteId 站点ID , 当前示例中未直接使用 , 根据需求可能用于扩展功能 。
* @param enableAction 操作类型 , 0 表示启用操作 , 其他值视为未知操作 。
* @return 包含冲突范围栏目的提示信息 , 如果没有冲突则返回空字符串 。
* /
private String generateConflictMessage ( Integer schemeId , Integer siteId , Integer enableAction ) {
// 调用 hasOverlapWithOtherEnabled 确认是否有重叠
// 确认当前悬浮栏方案是否与其他方案存在范围 重叠
if ( ! hasOverlapWithOtherEnabled ( schemeId , siteId ) ) {
return "" ; // 无冲突则返回空字符串
return "" ; // 若无重叠,直接返回空字符串表示无冲突
}
// 获取所有悬浮栏方案的范围ID
List < SysFloatingColumnSchemeScopeOfApplication > allScopes = scopeOfApplicationMapper . selectList ( null ) ;
Map < Integer , Set < Integer > > allScopeIdMap = allScopes . stream ( )
. collect ( Collectors . groupingBy (
SysFloatingColumnSchemeScopeOfApplication : : getFloatingBarSchemeId ,
Collectors . flatMapping ( scope - > Arrays . stream ( scope . getApplicationScopeId ( ) . split ( "," ) ) , Collectors . mapping ( Integer : : parseInt , Collectors . toSet ( ) ) )
) ) ;
// 获取当前方案的范围ID
Set < Integer > currentScopeIds = allScopeIdMap . getOrDefault ( schemeId , Collections . emptySet ( ) ) ;
// 找出与其他悬浮栏方案重复的范围ID
Set < Integer > duplicateScopeIds = allScopeIdMap . values ( ) . stream ( )
. filter ( ids - > ! ids . equals ( currentScopeIds ) & & ! ids . isEmpty ( ) )
. flatMap ( Set : : stream )
. filter ( currentScopeIds : : contains )
. collect ( Collectors . toSet ( ) ) ;
// 查询重复范围对应的栏目名称
List < String > duplicateScopeNames = columnMapper . selectList ( new LambdaQueryWrapper < SysColumn > ( ) . in ( SysColumn : : getId , duplicateScopeIds ) )
. stream ( )
. map ( SysColumn : : getColumnName )
. collect ( Collectors . toList ( ) ) ;
// 获取与当前悬浮栏方案ID相关的冲突范围ID集合
List < SysFloatingColumnSchemeScopeOfApplication > conflictingScopes = scopeOfApplicationMapper . selectList ( new LambdaQueryWrapper < SysFloatingColumnSchemeScopeOfApplication > ( ) . eq ( SysFloatingColumnSchemeScopeOfApplication : : getFloatingBarSchemeId , schemeId ) ) ;
// 构建并返回提示信息
if ( ! duplicateScopeNames . isEmpty ( ) ) {
String scopesJoined = String . join ( "”, “" , duplicateScopeNames ) ;
if ( enableAction = = 0 ) { // 启用操作
return "栏目:“" + scopesJoined + "”已存在于其他悬浮栏配置中,请处理重复后再尝试启用。" ;
} else if ( enableAction = = 1 ) { // 禁用操作
return "注意:禁用操作可能会影响到栏目“" + scopesJoined + "”在其他悬浮栏的配置,请谨慎操作。" ;
} else {
return "未知的操作类型" ;
}
// 将范围ID字符串转换为整数集合
Set < Integer > conflictScopeIds = conflictingScopes . stream ( ) . flatMap ( scope - > Arrays . stream ( scope . getApplicationScopeId ( ) . split ( "," ) ) ) . map ( Integer : : parseInt ) . collect ( Collectors . toSet ( ) ) ;
//查询当前已经启用的悬浮栏方案下的的应用范围跟当前设置的范围有重复的就只提出出来重复的id
conflictScopeIds . retainAll ( checkBoundByColumnId ( conflictScopeIds , siteId ) ) ;
// 根据冲突范围ID查询对应的栏目名称
List < String > conflictingScopeNames = columnMapper . selectList ( new LambdaQueryWrapper < SysColumn > ( ) . in ( SysColumn : : getId , conflictScopeIds ) ) . stream ( ) . map ( SysColumn : : getColumnName ) . collect ( Collectors . toList ( ) ) ;
// 根据操作类型生成具体的提示信息
if ( enableAction = = 0 ) { // 启用操作
// 拼接冲突范围名称,提醒用户需先解决冲突
return "栏目:“" + String . join ( "”, “" , conflictingScopeNames ) + "”已设置有悬浮栏,请先移除相关设置再尝试启用。" ;
} else {
return "" ; // 逻辑上这里应该不会到达,因为之前已确认有重叠,但为了完整性保留
return "未知的操作类型" ;
}
}
private Set < Integer > checkBoundByColumnId ( Set < Integer > columnIds , Integer siteId ) {
// 构造SQL查询条件,用于查找所有启用的悬浮栏方案及其范围
/*String sqlInCondition = columnIds.stream().map(Object::toString).collect(Collectors.joining(","));*/ // 移除了外部的括号
List < SysFloatingColumnSchemeScopeOfApplication > enabledConflictingScopes = scopeOfApplicationMapper . selectList ( new LambdaQueryWrapper < SysFloatingColumnSchemeScopeOfApplication > ( ) . inSql ( SysFloatingColumnSchemeScopeOfApplication : : getFloatingBarSchemeId , "SELECT id FROM sys_floating_column_scheme WHERE is_disable = 0 AND site_id = " + siteId ) . in ( SysFloatingColumnSchemeScopeOfApplication : : getApplicationScopeId , columnIds ) ) ;
// 转换为范围ID集合
Set < Integer > duplicateScopeIds = new HashSet < > ( ) ;
for ( SysFloatingColumnSchemeScopeOfApplication scope : enabledConflictingScopes ) {
duplicateScopeIds . addAll ( Arrays . stream ( scope . getApplicationScopeId ( ) . split ( "," ) ) . map ( Integer : : parseInt ) . collect ( Collectors . toSet ( ) ) ) ;
}
return duplicateScopeIds ;
}
// 新增方法:统计当前站点下已启用的全局悬浮栏数量
@ -398,4 +442,8 @@ public class SysFloatingColumnSchemeServiceImpl extends ServiceImpl<SysFloatingC
return baseMapper . selectCount ( new LambdaQueryWrapper < SysFloatingColumnScheme > ( ) . eq ( SysFloatingColumnScheme : : getSiteId , siteId ) . eq ( SysFloatingColumnScheme : : getIsGlobal , 1 ) . eq ( SysFloatingColumnScheme : : getIsDisable , false ) ) ;
}
private String getColumnNameById ( String overlapId ) {
return columnMapper . getColumnNamesById ( overlapId ) ;
}
}