@@ -2,6 +2,7 @@ package com.ruoyi.jarvis.service.impl;
import com.ruoyi.jarvis.domain.OrderRows ;
import com.ruoyi.jarvis.domain.OrderRows ;
import com.ruoyi.jarvis.domain.JDOrder ;
import com.ruoyi.jarvis.domain.JDOrder ;
import com.ruoyi.jarvis.domain.SuperAdmin ;
import com.ruoyi.jarvis.domain.WeComShareLinkLogisticsJob ;
import com.ruoyi.jarvis.domain.WeComShareLinkLogisticsJob ;
import com.ruoyi.jarvis.service.IInstructionService ;
import com.ruoyi.jarvis.service.IInstructionService ;
import com.ruoyi.jarvis.service.IOrderRowsService ;
import com.ruoyi.jarvis.service.IOrderRowsService ;
@@ -61,6 +62,9 @@ public class InstructionServiceImpl implements IInstructionService {
@Autowired ( required = false )
@Autowired ( required = false )
private com . ruoyi . jarvis . service . ITencentDocDelayedPushService tencentDocDelayedPushService ;
private com . ruoyi . jarvis . service . ITencentDocDelayedPushService tencentDocDelayedPushService ;
/** 与 {@link com.ruoyi.jarvis.service.impl.WeComInboundServiceImpl#WE_COM_SUPER_USER_ID} 一致:该账号在京统计中视为全局视角 */
private static final String WE_COM_SUPER_GLOBAL_STATS_USER = " LinPingFan " ;
/** 与企微物流分享链解析一致 */
/** 与企微物流分享链解析一致 */
private static final Pattern JD_3CN = Pattern . compile ( " https://3 \\ .cn/[A-Za-z0-9 \\ -]+ " ) ;
private static final Pattern JD_3CN = Pattern . compile ( " https://3 \\ .cn/[A-Za-z0-9 \\ -]+ " ) ;
@@ -82,6 +86,11 @@ public class InstructionServiceImpl implements IInstructionService {
@Override
@Override
public List < String > execute ( String command , boolean forceGenerate , boolean isFromConsole ) {
public List < String > execute ( String command , boolean forceGenerate , boolean isFromConsole ) {
return execute ( command , forceGenerate , isFromConsole , null ) ;
}
@Override
public List < String > execute ( String command , boolean forceGenerate , boolean isFromConsole , String wecomUserId ) {
// 存储接收的消息到Redis队列
// 存储接收的消息到Redis队列
storeMessageToRedis ( " instruction:request " , command ) ;
storeMessageToRedis ( " instruction:request " , command ) ;
@@ -99,7 +108,7 @@ public class InstructionServiceImpl implements IInstructionService {
// 一级命令分流:京系(统计/订单)、录单/慢单、转链/礼金…
// 一级命令分流:京系(统计/订单)、录单/慢单、转链/礼金…
if ( input . startsWith ( " 京 " ) | | menuKeywords ( ) . contains ( input ) ) {
if ( input . startsWith ( " 京 " ) | | menuKeywords ( ) . contains ( input ) ) {
result = Collections . singletonList ( handleJingFen ( input . replaceFirst ( " ^京 " , " " ) ) ) ;
result = Collections . singletonList ( handleJingFen ( input . replaceFirst ( " ^京 " , " " ) , wecomUserId )) ;
}
}
// TF/H/生/拼多多 生成类指令
// TF/H/生/拼多多 生成类指令
else if ( input . startsWith ( " TF " ) ) {
else if ( input . startsWith ( " TF " ) ) {
@@ -130,6 +139,77 @@ public class InstructionServiceImpl implements IInstructionService {
return result ;
return result ;
}
}
/**
* 「京」统计/订单所用京粉订单数据源:企微成员按超级管理员绑定 unionId; 全局视角排除「不参与订单统计」联盟。
*/
private static final class JingStatsScope {
private final List < OrderRows > rows ;
/** 可为 null: 禁止访问统计( 不参与统计等) */
private final String denyMessage ;
/** 回复前缀,标明当前统计归属 */
private final String replyPrefix ;
private JingStatsScope ( List < OrderRows > rows , String denyMessage , String replyPrefix ) {
this . rows = rows ! = null ? rows : Collections . emptyList ( ) ;
this . denyMessage = denyMessage ;
this . replyPrefix = replyPrefix ! = null ? replyPrefix : " " ;
}
static JingStatsScope denied ( String msg ) {
return new JingStatsScope ( Collections . emptyList ( ) , msg , " " ) ;
}
static JingStatsScope ok ( List < OrderRows > rows , String replyPrefix ) {
return new JingStatsScope ( rows , null , replyPrefix ) ;
}
}
private List < Long > buildExcludeUnionIdsForStats ( ) {
List < Long > excludeUnionIds = new ArrayList < > ( ) ;
List < SuperAdmin > superAdminList = superAdminService . selectSuperAdminList ( null ) ;
if ( superAdminList ! = null ) {
for ( SuperAdmin admin : superAdminList ) {
if ( admin . getIsCount ( ) ! = null & & admin . getIsCount ( ) = = 0 & & admin . getUnionId ( ) ! = null & & ! admin . getUnionId ( ) . trim ( ) . isEmpty ( ) ) {
try {
excludeUnionIds . add ( Long . parseLong ( admin . getUnionId ( ) . trim ( ) ) ) ;
} catch ( NumberFormatException ignored ) {
}
}
}
}
return excludeUnionIds ;
}
private JingStatsScope resolveJingStatsScope ( String wecomUserId ) {
if ( wecomUserId = = null | | wecomUserId . trim ( ) . isEmpty ( )
| | WE_COM_SUPER_GLOBAL_STATS_USER . equals ( wecomUserId . trim ( ) ) ) {
List < OrderRows > all = orderRowsService . selectOrderRowsListWithFilter ( new OrderRows ( ) , null , null , buildExcludeUnionIdsForStats ( ) ) ;
return JingStatsScope . ok ( all , " " ) ;
}
String wxUser = wecomUserId . trim ( ) ;
SuperAdmin sa = superAdminService . selectSuperAdminByWecomUserId ( wxUser ) ;
if ( sa = = null ) {
return JingStatsScope . ok ( Collections . emptyList ( ) , " " ) ;
}
if ( sa . getIsCount ( ) ! = null & & sa . getIsCount ( ) = = 0 ) {
return JingStatsScope . denied ( " 「京统计」 \ n \ n当前企微账号在后台「超级管理员」中标记为不参与订单统计, 无法使用统计与订单类京指令。 \ n如需开通请联系管理员。 " ) ;
}
if ( sa . getUnionId ( ) = = null | | sa . getUnionId ( ) . trim ( ) . isEmpty ( ) ) {
return JingStatsScope . denied ( " 「京统计」 \ n \ n当前企微账号未绑定联盟ID, 无法匹配京粉订单。 \ n请在后台「超级管理员」中维护该账号对应行的联盟ID。 " ) ;
}
try {
long uid = Long . parseLong ( sa . getUnionId ( ) . trim ( ) ) ;
OrderRows probe = new OrderRows ( ) ;
probe . setUnionId ( uid ) ;
List < OrderRows > scoped = orderRowsService . selectOrderRowsListWithFilter ( probe , null , null , Collections . emptyList ( ) ) ;
String namePart = sa . getName ( ) ! = null & & ! sa . getName ( ) . trim ( ) . isEmpty ( ) ? sa . getName ( ) . trim ( ) : " 未命名 " ;
String prefix = " 【联盟 " + sa . getUnionId ( ) . trim ( ) + " · " + namePart + " 】 \ n " ;
return JingStatsScope . ok ( scoped , prefix ) ;
} catch ( NumberFormatException e ) {
return JingStatsScope . denied ( " 「京统计」 \ n \ n联盟ID格式不正确, 请联系管理员检查「超级管理员」配置。 " ) ;
}
}
/**
/**
* 将消息存储到Redis队列, 最多保留100条
* 将消息存储到Redis队列, 最多保留100条
* @param key Redis键
* @param key Redis键
@@ -202,7 +282,7 @@ public class InstructionServiceImpl implements IInstructionService {
return new HashSet < > ( Arrays . asList ( " 菜单 " , " 今日统计 " , " 昨日统计 " , " 三日统计 " , " 七日统计 " , " 一个月统计 " , " 两个月统计 " , " 三个月统计 " , " 这个月统计 " , " 上个月统计 " , " 今日订单 " , " 昨日订单 " , " 七日订单 " , " 总统计 " ) ) ;
return new HashSet < > ( Arrays . asList ( " 菜单 " , " 今日统计 " , " 昨日统计 " , " 三日统计 " , " 七日统计 " , " 一个月统计 " , " 两个月统计 " , " 三个月统计 " , " 这个月统计 " , " 上个月统计 " , " 今日订单 " , " 昨日订单 " , " 七日订单 " , " 总统计 " ) ) ;
}
}
private String handleJingFen ( String cmd ) {
private String handleJingFen ( String cmd , String wecomUserId ) {
String action = cmd . trim ( ) ;
String action = cmd . trim ( ) ;
if ( action . isEmpty ( ) | | action . equals ( " 菜单 " ) ) {
if ( action . isEmpty ( ) | | action . equals ( " 菜单 " ) ) {
return jingMenu ( ) ;
return jingMenu ( ) ;
@@ -217,37 +297,40 @@ public class InstructionServiceImpl implements IInstructionService {
return textExternalShareLinkLogisticsDelete ( rest ) ;
return textExternalShareLinkLogisticsDelete ( rest ) ;
}
}
// 取出所有订单(排除被删除/无效:这里沿用 OrderRowsService 的常规查询,必要时可增加过滤参数)
JingStatsScope scope = resolveJingStatsScope ( wecomUserId ) ;
List < OrderRows > all = orderRowsService . selectOrderRowsList ( new OrderRows ( ) ) ;
if ( scope . denyMessage ! = null ) {
if ( all = = null ) all = Collections . emptyList ( ) ;
return scope . denyMessage ;
}
List < OrderRows > all = scope . rows ;
String header = scope . replyPrefix ;
switch ( action ) {
switch ( action ) {
case " 今日统计 " :
case " 今日统计 " :
return statsText ( filterByDays ( all , 0 ) , " 今日统计 " ) ;
return header + statsText( filterByDays ( all , 0 ) , " 今日统计 " ) ;
case " 昨日统计 " :
case " 昨日统计 " :
return statsText ( filterYesterday ( all ) , " 昨日统计 " ) ;
return header + statsText( filterYesterday ( all ) , " 昨日统计 " ) ;
case " 三日统计 " :
case " 三日统计 " :
return statsText ( filterByRange ( all , 3 ) , " 三日统计 " ) ;
return header + statsText( filterByRange ( all , 3 ) , " 三日统计 " ) ;
case " 七日统计 " :
case " 七日统计 " :
return statsText ( filterByRange ( all , 7 ) , " 七日统计 " ) ;
return header + statsText( filterByRange ( all , 7 ) , " 七日统计 " ) ;
case " 一个月统计 " :
case " 一个月统计 " :
return statsText ( filterByRange ( all , 30 ) , " 一个月统计 " ) ;
return header + statsText( filterByRange ( all , 30 ) , " 一个月统计 " ) ;
case " 两个月统计 " :
case " 两个月统计 " :
return statsText ( filterByRange ( all , 60 ) , " 两个月统计 " ) ;
return header + statsText( filterByRange ( all , 60 ) , " 两个月统计 " ) ;
case " 三个月统计 " :
case " 三个月统计 " :
return statsText ( filterByRange ( all , 90 ) , " 三个月统计 " ) ;
return header + statsText( filterByRange ( all , 90 ) , " 三个月统计 " ) ;
case " 这个月统计 " :
case " 这个月统计 " :
return statsText ( filterThisMonth ( all ) , " 这个月统计 " ) ;
return header + statsText( filterThisMonth ( all ) , " 这个月统计 " ) ;
case " 上个月统计 " :
case " 上个月统计 " :
return statsText ( filterLastMonth ( all ) , " 上个月统计 " ) ;
return header + statsText( filterLastMonth ( all ) , " 上个月统计 " ) ;
case " 总统计 " :
case " 总统计 " :
return statsText ( all , " 总统计 " ) ;
return header + statsText( all , " 总统计 " ) ;
case " 今日订单 " :
case " 今日订单 " :
return listOrders ( filterByDays ( all , 0 ) , " 今日订单 " ) ;
return header + listOrders( filterByDays ( all , 0 ) , " 今日订单 " ) ;
case " 昨日订单 " :
case " 昨日订单 " :
return listOrders ( filterYesterday ( all ) , " 昨日订单 " ) ;
return header + listOrders( filterYesterday ( all ) , " 昨日订单 " ) ;
case " 七日订单 " :
case " 七日订单 " :
return listOrders ( filterByRange ( all , 7 ) , " 七日订单 " ) ;
return header + listOrders( filterByRange ( all , 7 ) , " 七日订单 " ) ;
default :
default :
// 高级命令: 违规N、SKU、搜索、JF… 此处按需扩展
// 高级命令: 违规N、SKU、搜索、JF… 此处按需扩展
if ( action . startsWith ( " 高级 " ) ) {
if ( action . startsWith ( " 高级 " ) ) {
@@ -2338,7 +2421,8 @@ public class InstructionServiceImpl implements IInstructionService {
// ===== 工具 =====
// ===== 工具 =====
private String jingMenu ( ) {
private String jingMenu ( ) {
return " 「京粉 · 菜单」 \ n \ n "
return " 「京粉 · 菜单」 \ n \ n "
+ " 企微/机器人前请加「京」,例如:京今日统计 \ n \ n "
+ " 企微/机器人前请加「京」,例如:京今日统计 \ n "
+ " 说明: 企微内统计仅含当前账号在「超级管理员」绑定的联盟ID; 标记为不参与订单统计的联盟不会在全局汇总中出现( 与后台京粉订单列表统计一致) 。 \ n \ n "
+ " —— 统计 —— \ n "
+ " —— 统计 —— \ n "
+ " 今日统计、昨日统计、三日统计、七日统计 \ n "
+ " 今日统计、昨日统计、三日统计、七日统计 \ n "
+ " 一个月统计、两个月统计、三个月统计 \ n "
+ " 一个月统计、两个月统计、三个月统计 \ n "