فهرست منبع

fix 微信客服关联登录账号;转接会话

zoujiajian 1 سال پیش
والد
کامیت
f4e94cbd65

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/mapper/corp/kf/CorpKfServicerSessionRecordMapper.java

@@ -15,4 +15,6 @@ import java.util.List;
  */
 public interface CorpKfServicerSessionRecordMapper extends BaseMapper<CorpKfServicerSessionRecord> {
 	List<CorpKfServicerDto> getAvailableServicer(@Param("openKfId") String openKfId);
+
+	List<CorpKfServicerSessionRecord> selectSessionByCondition(@Param("openKfId") String openKfId, @Param("servicerUserid") String servicerUserid, @Param("transUserIds") List<String> transUserIds, @Param("transNum") Integer transNum);
 }

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/request/sys/SysCorpFollowReq.java

@@ -54,4 +54,6 @@ public class SysCorpFollowReq {
 	private Integer status;
 
 	private String img;
+
+	private String openKfId;
 }

+ 44 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CorpKfAccountChildView.java

@@ -0,0 +1,44 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpKfAccountChildView
+ * 创建者: JavaZou
+ * 创建时间:2025/1/13 17:42
+ */
+@Getter
+@Setter
+@SearchBean(tables = "corp_kf_account cf")
+public class CorpKfAccountChildView {
+	@DbField("cf.open_kf_id")
+	private String openKfId;
+
+	@DbField("cf.name")
+	private String name;
+
+	@DbIgnore
+	private List<CorpKfFollowView> child;
+
+	@Getter
+	@Setter
+	@SearchBean(tables = "corp_follow cf left join sys_corp_follow_relate sfr on sfr.follow_id = cf.userid" +
+			" left join sys_corp_follow sf on sf.id = sfr.mid")
+	public static class CorpKfFollowView{
+		@DbField("cf.userid")
+		private String followId;
+
+		@DbField("cf.name")
+		private String followName;
+
+		@DbField("concat(sf.name,'(',cf.name,')')")
+		private String showName;
+	}
+}

+ 115 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CorpKfServicerStatisticView.java

@@ -0,0 +1,115 @@
+package com.cyksj.model.views;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpKfServicerStatisticView
+ * 创建者: JavaZou
+ * 创建时间:2025/1/13 16:29
+ */
+@Getter
+@Setter
+@SearchBean(tables = "corp_kf_servicer_statistic cs",
+		where = ":time:",
+		groupBy = "open_kf_id,servicer_userid")
+public class CorpKfServicerStatisticView {
+	/**
+	 * openkfid
+	 */
+	@DbField("cs.open_kf_id")
+	private String openKfId;
+
+	/**
+	 * 客服人员 ID
+	 */
+	@DbField("cs.servicer_userid")
+	private String servicerUserid;
+
+	/**
+	 * 账号
+	 */
+	@DbIgnore
+	@TableField(exist = false)
+	private String name;
+
+	/**
+	 * 企业成员名
+	 */
+	@DbIgnore
+	@TableField(exist = false)
+	private String followName;
+
+	/**
+	 * 接入人工会话数
+	 */
+	@DbField("sum(cs.session_cnt)")
+	private Integer sessionCnt;
+
+	/**
+	 * 咨询客户数
+	 */
+	@DbField("sum(cs.customer_cnt)")
+	private Integer customerCnt;
+
+	/**
+	 * 咨询消息总数
+	 */
+	@DbField("sum(cs.customer_msg_cnt)")
+	private Integer customerMsgCnt;
+
+	/**
+	 * 人工回复率
+	 */
+	@DbField("sum(cs.reply_rate)")
+	private BigDecimal replyRate;
+
+	/**
+	 * 平均首次响应时长(秒)
+	 */
+	@DbField("sum(cs.first_reply_average_sec)")
+	private BigDecimal firstReplyAverageSec;
+
+	/**
+	 * 满意度评价发送数
+	 */
+	@DbField("sum(cs.satisfaction_investgate_cnt)")
+	private Integer satisfactionInvestgateCnt;
+
+	/**
+	 * 满意度参评率
+	 */
+	@DbField("sum(cs.satisfaction_participation_rate)")
+	private BigDecimal satisfactionParticipationRate;
+
+	/**
+	 * 满意评价占比
+	 */
+	@DbField("sum(cs.satisfied_rate)")
+	private BigDecimal satisfiedRate;
+
+	/**
+	 * 一般评价占比
+	 */
+	@DbField("sum(cs.middling_rate)")
+	private BigDecimal middlingRate;
+
+	/**
+	 * 不满意评价占比
+	 */
+	@DbField("sum(cs.dissatisfied_rate)")
+	private BigDecimal dissatisfiedRate;
+
+	/**
+	 * 被拒收消息的客户数
+	 */
+	@DbField("sum(cs.msg_rejected_customer_cnt)")
+	private Integer msgRejectedCustomerCnt;
+}

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/model/views/CorpKfTransUserView.java

@@ -19,7 +19,7 @@ public class CorpKfTransUserView {
 	@DbField("cf.external_userid")
 	private String externalUserid;
 
-	@DbField("cu.name")
+	@DbField("cu.nickname")
 	private String name;
 
 	@DbField("cf.open_kf_id")

+ 15 - 0
netflix-dao/src/main/resources/mapper/CorpKfServicerSessionRecordMapper.xml

@@ -12,4 +12,19 @@
         group by servicer_userid
         order by num asc
     </select>
+
+    <select id="selectSessionByCondition" resultType="com.cyksj.model.entity.CorpKfServicerSessionRecord">
+        select * from corp_kf_servicer_session_record where open_kf_id = #{openKfId}
+        and servicer_userid = #{servicerUserid}
+        and service_state = 0
+        <if test="transUserIds != null and transUserIds.size() > 0">
+            and external_userid in
+            <foreach collection="transUserIds" item="item" open="(" separator="," close=")">
+                #{item}
+            </foreach>
+        </if>
+        <if test="transNum!=null and transNum > 0">
+            order by rand() limit #{transNum}
+        </if>
+    </select>
 </mapper>

+ 27 - 24
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpServiceImpl.java

@@ -734,9 +734,7 @@ public class CorpServiceImpl implements CorpService {
 		if (changeType == 2) {
 			//设置表中会话状态
 			setDbSessionState(openKfId, oldServicerUserId, externalUserId, sendDate, changeType, msgId, msgCode);
-			//记录新的客服会话
-			String newServicerUserid = wxCpKfMsgItem.getNewServicerUserid();
-			transCorpKfSessionToServicer(corpId, openKfId, oldServicerUserId, newServicerUserid, externalUserId, changeType, 3, sendDate, msgId);
+			transCorpKfSessionToServicer(corpId, openKfId, oldServicerUserId, newServicerUserId, externalUserId, changeType, 3, sendDate, msgId);
 		}
 		//3-结束会话 4-重新接入已结束/已转接会话
 		if (changeType == 3 || changeType == 4) {
@@ -806,28 +804,32 @@ public class CorpServiceImpl implements CorpService {
 	 * serviceState 0未处理 1由智能助手接待 2待接入池排队中 3由人工接待 4 已结束/未开始
 	 */
 	private void transCorpKfSessionToServicer(String corpId, String openKfId, String oldServicerUserId, String userid, String externalUserId, Integer changeType, Integer serviceState, Date sendTime, String msgid) throws Exception {
-		//记录接待人员会话
-		CorpKfServicerSessionRecord corpKfServicerSessionRecord = new CorpKfServicerSessionRecord();
-		corpKfServicerSessionRecord.setOpenKfId(openKfId);
-		corpKfServicerSessionRecord.setServiceState(0);
-		corpKfServicerSessionRecord.setFromUserid(oldServicerUserId);
-		corpKfServicerSessionRecord.setServicerUserid(userid);
-		corpKfServicerSessionRecord.setExternalUserid(externalUserId);
-		corpKfServicerSessionRecord.setChangeType(changeType);
-		corpKfServicerSessionRecord.setStartTime(sendTime);
-		corpKfServicerSessionRecord.setMsgid(msgid);
-		corpKfServicerSessionRecordMapper.insert(corpKfServicerSessionRecord);
 		//调用微信客服接口 变更会话状态
-		wxCorpOps.transCorpKfSessionToServicer(corpId, openKfId, userid, externalUserId, serviceState);
-		//等待用户删除
-		delQueueUser(openKfId, externalUserId, sendTime);
-		//同步这一次接待记录
-		if (serviceState == 3) {
-			corpKfAccountSessionChatMapper.update(null, Wrappers.lambdaUpdate(CorpKfAccountSessionChat.class)
-					.set(CorpKfAccountSessionChat::getSessionId, corpKfServicerSessionRecord.getId())
-					.eq(CorpKfAccountSessionChat::getOpenKfId, openKfId)
-					.eq(CorpKfAccountSessionChat::getExternalUserid, externalUserId)
-					.isNull(CorpKfAccountSessionChat::getSessionId));
+		try {
+			wxCorpOps.transCorpKfSessionToServicer(corpId, openKfId, userid, externalUserId, serviceState);
+			//记录接待人员会话
+			CorpKfServicerSessionRecord corpKfServicerSessionRecord = new CorpKfServicerSessionRecord();
+			corpKfServicerSessionRecord.setOpenKfId(openKfId);
+			corpKfServicerSessionRecord.setServiceState(0);
+			corpKfServicerSessionRecord.setFromUserid(oldServicerUserId);
+			corpKfServicerSessionRecord.setServicerUserid(userid);
+			corpKfServicerSessionRecord.setExternalUserid(externalUserId);
+			corpKfServicerSessionRecord.setChangeType(changeType);
+			corpKfServicerSessionRecord.setStartTime(sendTime);
+			corpKfServicerSessionRecord.setMsgid(msgid);
+			corpKfServicerSessionRecordMapper.insert(corpKfServicerSessionRecord);
+			//等待用户删除
+			delQueueUser(openKfId, externalUserId, sendTime);
+			//同步这一次接待记录
+			if (serviceState == 3) {
+				corpKfAccountSessionChatMapper.update(null, Wrappers.lambdaUpdate(CorpKfAccountSessionChat.class)
+						.set(CorpKfAccountSessionChat::getSessionId, corpKfServicerSessionRecord.getId())
+						.eq(CorpKfAccountSessionChat::getOpenKfId, openKfId)
+						.eq(CorpKfAccountSessionChat::getExternalUserid, externalUserId)
+						.isNull(CorpKfAccountSessionChat::getSessionId));
+			}
+		} catch (Exception e) {
+			log.error("创建新的会话错误:{}", StringUtil.getErrorText(e));
 		}
 	}
 
@@ -967,6 +969,7 @@ public class CorpServiceImpl implements CorpService {
 		CorpKfServicerSessionRecord corpKfServicerSessionRecord = corpKfServicerSessionRecordMapper.selectOne(Wrappers.lambdaQuery(CorpKfServicerSessionRecord.class)
 				.eq(CorpKfServicerSessionRecord::getOpenKfId, chat.getOpenKfId())
 				.eq(CorpKfServicerSessionRecord::getExternalUserid, chat.getExternalUserid())
+				.orderByDesc(CorpKfServicerSessionRecord::getId)
 				.eq(CorpKfServicerSessionRecord::getServiceState, 0)
 				.last("limit 1"));
 		if (corpKfServicerSessionRecord != null) chat.setSessionId(corpKfServicerSessionRecord.getId());

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/corp/kf/CorpKfService.java

@@ -30,7 +30,7 @@ public interface CorpKfService {
 
 	String getUrl(String openKfId, String scene) throws Exception;
 
-	void transCustomer(String followId, String toFollowId, Integer transNum, List<String> transUserIds) throws Exception;
+	void transCustomer(String followId, String toFollowId, Integer transNum, List<String> transUserIds, String openKfId) throws Exception;
 
 	List<CorpKfAccount> getCorpKfAccountByUId(long cmsUserId);
 }

+ 16 - 37
netflix-service/src/main/java/com/cyksj/service/corp/kf/impl/CorpKfServiceImpl.java

@@ -8,9 +8,13 @@ import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.StringUtil;
 import com.cyksj.config.corp.YHLXWxCorpConfig;
 import com.cyksj.mapper.corp.CorpFollowMapper;
-import com.cyksj.mapper.corp.kf.*;
+import com.cyksj.mapper.corp.kf.CorpKfAccountFollowMapper;
+import com.cyksj.mapper.corp.kf.CorpKfAccountMapper;
+import com.cyksj.mapper.corp.kf.CorpKfAccountSessionConfigMapper;
+import com.cyksj.mapper.corp.kf.CorpKfServicerSessionRecordMapper;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.kf.*;
@@ -293,45 +297,20 @@ public class CorpKfServiceImpl implements CorpKfService {
 	 * 转接客服
 	 */
 	@Override
-	public void transCustomer(String followId, String toFollowId, Integer transNum, List<String> transUserIds) throws Exception {
-		List<CorpKfAccountFollow> corpKfAccountFollows = corpKfAccountFollowMapper.selectList(Wrappers.lambdaQuery(CorpKfAccountFollow.class)
-				.apply(String.format("JSON_CONTAINS(user_id_list,'\"%s\"')", followId)));
-		List<String> openKfIds = new ArrayList<>();
-		for (CorpKfAccountFollow corpKfAccountFollow : corpKfAccountFollows) {
-			String userIdList = corpKfAccountFollow.getUserIdList();
-			List<String> followIds = Jsons.parseList(userIdList, String.class);
-			followIds.remove(followIds);
-			followIds.add(toFollowId);
-			corpKfAccountFollowMapper.updateById(corpKfAccountFollow);
-			if (!openKfIds.contains(corpKfAccountFollow.getOpenKfId())) {
-				openKfIds.add(corpKfAccountFollow.getOpenKfId());
-			}
-		}
-		List<CorpKfServicerSessionRecord> corpKfServicerSessionRecords = corpKfServicerSessionRecordMapper.selectList(Wrappers.lambdaQuery(CorpKfServicerSessionRecord.class)
-				.eq(CorpKfServicerSessionRecord::getServiceState, 0)
-				.apply(transNum != null, String.format("order by rand() limit %s", transNum))
-				.in(CollUtil.isNotEmpty(transUserIds), CorpKfServicerSessionRecord::getExternalUserid, transUserIds));
+	public void transCustomer(String followId, String toFollowId, Integer transNum, List<String> transUserIds, String openKfId) throws Exception {
+		List<CorpKfServicerSessionRecord> corpKfServicerSessionRecords = corpKfServicerSessionRecordMapper.selectSessionByCondition(openKfId, followId, transUserIds, transNum);
 		String corpId = yhlxWxCorpConfig.getCorpId();
-		//添加对应客服
-		for (String openKfId : openKfIds) {
-			CorpKfServicerResp corpKfServicerResp = wxCorpOps.getKfServicerList(yhlxWxCorpConfig.getCorpId(), openKfId);
-			List<CorpKfServicerResp.CorpKfServicer> servicerList = corpKfServicerResp.getServicerList();
-			Set<String> dutyFollowIds = new HashSet<>();
-			for (CorpKfServicerResp.CorpKfServicer corpKfServicer : servicerList) {
-				String userid = corpKfServicer.getUserid();
-				if (userid != null) {
-					dutyFollowIds.add(userid);
-				}
-			}
-			if (!dutyFollowIds.isEmpty()) {
-				dutyFollowIds.remove(followId);
-				dutyFollowIds.add(toFollowId);
-				wxCorpOps.addCorpKfServicer(openKfId, dutyFollowIds);
-			}
-		}
 		for (CorpKfServicerSessionRecord corpKfServicerSessionRecord : corpKfServicerSessionRecords) {
 			//调用微信客服接口 变更会话状态
-			wxCorpOps.transCorpKfSessionToServicer(corpId, corpKfServicerSessionRecord.getOpenKfId(), toFollowId, corpKfServicerSessionRecord.getExternalUserid(), 3);
+			try {
+				wxCorpOps.transCorpKfSessionToServicer(corpId, corpKfServicerSessionRecord.getOpenKfId(), toFollowId, corpKfServicerSessionRecord.getExternalUserid(), 3);
+			} catch (Exception e) {
+				String errorText = StringUtil.getErrorText(e);
+				if (errorText.contains("conversation end")) {
+					corpKfServicerSessionRecord.setServiceState(1);
+					corpKfServicerSessionRecordMapper.updateById(corpKfServicerSessionRecord);
+				}
+			}
 		}
 	}
 

+ 1 - 0
netflix-service/src/main/java/com/cyksj/service/sys/impl/SysCorpFollowServiceImpl.java

@@ -172,6 +172,7 @@ public class SysCorpFollowServiceImpl extends ServiceImpl<SysCorpFollowMapper, S
 					corpFollowMapper.updateById(follow);
 				});
 			}
+			updateById(sysCorpFollow);
 		}
 	}
 

+ 15 - 3
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/wxkf/CorpKfController.java

@@ -1,6 +1,7 @@
 package com.cyksj.web.controller.manage.corp.wxkf;
 
 import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.annotation.Log;
 import com.cyksj.dto.Result;
@@ -12,6 +13,7 @@ import com.cyksj.model.entity.*;
 import com.cyksj.model.request.CorpKfDutySetReq;
 import com.cyksj.model.request.corp.kf.CorpKfDutyReq;
 import com.cyksj.model.views.CorpKfDutyServicersStatusView;
+import com.cyksj.model.views.CorpKfServicerStatisticView;
 import com.cyksj.model.views.CorpKfUserChatRecordView;
 import com.cyksj.model.views.SysCorpFollowView;
 import com.cyksj.service.corp.kf.CorpKfService;
@@ -167,7 +169,7 @@ public class CorpKfController {
 	 * 数据统计
 	 */
 	@GetMapping("/get/statistics")
-	public Result<SearchResult<CorpKfServicerStatistic>> getStatisticsData() {
+	public Result<SearchResult<CorpKfServicerStatisticView>> getStatisticsData(String startTime, String endTime) {
 		long adminId = StpUtil.getLoginIdAsLong();
 		Boolean rootRole = cmsUserService.isRootRole(adminId);
 		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
@@ -176,8 +178,18 @@ public class CorpKfController {
 					.eq(CorpFollow::getCmsUserId, adminId)).stream().map(CorpFollow::getUserid).collect(Collectors.toList());
 			builder.field(CorpKfServicerStatistic::getServicerUserid, userids).op(Operator.InList);
 		}
-		SearchResult<CorpKfServicerStatistic> search = beanSearcher.search(CorpKfServicerStatistic.class, builder.build());
-		search.getDataList().forEach(data->{
+		String timeSql = StrUtil.EMPTY;
+		if (startTime != null) {
+			timeSql += String.format(" statistics_date>= '%s'", startTime);
+		}
+		if (endTime != null) {
+			timeSql += String.format(" and statistics_date <= '%s'", endTime);
+		}
+		if (StrUtil.isNotEmpty(timeSql)) {
+			builder.put("time", timeSql);
+		}
+		SearchResult<CorpKfServicerStatisticView> search = beanSearcher.search(CorpKfServicerStatisticView.class, builder.build());
+		search.getDataList().forEach(data -> {
 			SysCorpFollowView sysCorpFollowView = beanSearcher.searchFirst(SysCorpFollowView.class, MapUtils.builder().field(SysCorpFollowView::getFollowId, data.getServicerUserid()).build());
 			if (sysCorpFollowView != null) {
 				data.setName(sysCorpFollowView.getName());

+ 32 - 1
netflix-web/src/main/java/com/cyksj/web/controller/sys/SysCorpFollowController.java

@@ -1,14 +1,19 @@
 package com.cyksj.web.controller.sys;
 
 import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.util.Jsons;
 import com.cyksj.config.corp.YHLXWxCorpConfig;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.SysCorpFollowRelateMapper;
 import com.cyksj.mapper.corp.CorpUserFollowRelationMapper;
+import com.cyksj.mapper.corp.kf.CorpKfAccountFollowMapper;
+import com.cyksj.model.entity.CorpKfAccountFollow;
 import com.cyksj.model.entity.SysCorpFollow;
 import com.cyksj.model.entity.SysCorpFollowRelate;
 import com.cyksj.model.request.sys.SysCorpFollowReq;
+import com.cyksj.model.views.CorpKfAccountChildView;
 import com.cyksj.model.views.CorpKfTransUserView;
 import com.cyksj.model.views.SysCorpFollowView;
 import com.cyksj.model.views.SysCorpMasterFollowView;
@@ -18,14 +23,17 @@ import com.cyksj.service.corp.kf.CorpKfService;
 import com.cyksj.service.sys.SysCorpFollowService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -60,6 +68,8 @@ public class SysCorpFollowController {
 
 	private final SysCorpFollowRelateMapper sysCorpFollowRelateMapper;
 
+	private final CorpKfAccountFollowMapper corpKfAccountFollowMapper;
+
 	/**
 	 * 新增客服
 	 */
@@ -143,7 +153,7 @@ public class SysCorpFollowController {
 		String toFollowId = req.getToFollowId();
 		Long sid = req.getSid();
 		SysCorpFollowRelate sysCorpFollowRelate = sysCorpFollowRelateMapper.selectById(sid);
-		corpKfService.transCustomer(sysCorpFollowRelate.getFollowId(), toFollowId, req.getTransNum(), req.getTransUserIds());
+		corpKfService.transCustomer(sysCorpFollowRelate.getFollowId(), toFollowId, req.getTransNum(), req.getTransUserIds(), req.getOpenKfId());
 		sysCorpFollowRelate.setToFollowId(toFollowId);
 		sysCorpFollowRelateMapper.updateById(sysCorpFollowRelate);
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
@@ -157,4 +167,25 @@ public class SysCorpFollowController {
 		SearchResult<CorpKfTransUserView> search = beanSearcher.search(CorpKfTransUserView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
+
+	/**
+	 * 客服账号级联
+	 */
+	@GetMapping("/get/corp/kf/account/users")
+	public Result<List<CorpKfAccountChildView>> getCorpKfAccountUsers() throws Exception {
+		List<CorpKfAccountChildView> corpKfAccountChildViews = beanSearcher.searchAll(CorpKfAccountChildView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		for (CorpKfAccountChildView data : corpKfAccountChildViews) {
+			List<CorpKfAccountFollow> corpKfAccountFollows = corpKfAccountFollowMapper.selectList(Wrappers.lambdaQuery(CorpKfAccountFollow.class)
+					.eq(CorpKfAccountFollow::getOpenKfId, data.getOpenKfId()));
+			Set<String> followIds = new HashSet<>();
+			for (CorpKfAccountFollow corpKfAccountFollow : corpKfAccountFollows) {
+				followIds.addAll(Jsons.parseList(corpKfAccountFollow.getUserIdList(), String.class));
+			}
+			List<CorpKfAccountChildView.CorpKfFollowView> corpKfFollowViews = beanSearcher.searchAll(CorpKfAccountChildView.CorpKfFollowView.class, MapUtils.builder()
+					.field(CorpKfAccountChildView.CorpKfFollowView::getFollowId, followIds).op(Operator.InList)
+					.build());
+			data.setChild(corpKfFollowViews);
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(corpKfAccountChildViews);
+	}
 }