From 66627870a9c575d4285344f83ac79116b01d38ec Mon Sep 17 00:00:00 2001 From: sunxiwang Date: Fri, 6 Nov 2020 16:05:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=A2=E6=88=B7=E6=9D=A1=E4=BB=B6=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=8A=9F=E8=83=BD=E5=AE=8C=E5=96=84=EF=BC=9B=20?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E5=90=8C=E6=AD=A5=E5=BC=82=E6=AD=A5=E9=87=87?= =?UTF-8?q?=E7=94=A8=E5=A4=9A=E7=BA=BF=E7=A8=8B=E6=96=B9=E5=BC=8F=EF=BC=8C?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E6=89=B9=E9=87=8F=E8=8E=B7=E5=8F=96=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E8=AF=A6=E6=83=85=E6=8E=A5=E5=8F=A3=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E9=80=9F=E5=BA=A6=EF=BC=9B=20=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E5=88=97=E8=A1=A8=E5=AF=BC=E5=87=BA=E6=9A=82=E6=97=B6?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E5=AF=BC=E5=87=BA=E5=AE=A2=E6=88=B7=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wecom/WeCustomerController.java | 48 ++- .../src/main/resources/application.yml | 11 +- .../common/constant/WeConstans.java | 3 +- .../com/linkwechat/common/utils/Threads.java | 19 +- .../framework/manager/ShutdownManager.java | 3 + linkwe-ui/src/api/customer/index.js | 10 + .../src/views/customerManage/customer.vue | 30 +- .../wecom/client/WeCustomerClient.java | 10 + .../linkwechat/wecom/domain/WeCustomer.java | 16 +- .../dto/customer/ExternalUserDetail.java | 21 + .../domain/dto/customer/ExternalUserList.java | 4 + .../wecom/mapper/WeCustomerMapper.java | 12 +- .../wecom/service/IWeCustomerService.java | 13 +- .../impl/WeAccessTokenServiceImpl.java | 1 + .../service/impl/WeCustomerServiceImpl.java | 404 +++++++++--------- .../mapper/wecom/WeCustomerMapper.xml | 56 ++- 16 files changed, 411 insertions(+), 250 deletions(-) diff --git a/linkwe-admin/src/main/java/com/linkwechat/web/controller/wecom/WeCustomerController.java b/linkwe-admin/src/main/java/com/linkwechat/web/controller/wecom/WeCustomerController.java index 83d3df72..74a85014 100644 --- a/linkwe-admin/src/main/java/com/linkwechat/web/controller/wecom/WeCustomerController.java +++ b/linkwe-admin/src/main/java/com/linkwechat/web/controller/wecom/WeCustomerController.java @@ -8,10 +8,13 @@ import com.linkwechat.common.core.controller.BaseController; import com.linkwechat.common.core.domain.AjaxResult; import com.linkwechat.common.core.page.TableDataInfo; import com.linkwechat.common.enums.BusinessType; +import com.linkwechat.common.utils.Threads; import com.linkwechat.common.utils.poi.ExcelUtil; import com.linkwechat.wecom.domain.vo.WeMakeCustomerTag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -62,27 +65,27 @@ public class WeCustomerController extends BaseController return AjaxResult.success(weCustomerService.getCustomersByUserId(userId)); } -// /** -// * 导出企业微信客户列表 -// */ -// @PreAuthorize("@ss.hasPermi('wecom:customer:export')") -// @Log(title = "企业微信客户", businessType = BusinessType.EXPORT) -// @GetMapping("/export") -// public AjaxResult export(WeCustomer weCustomer) -// { -// List list = weCustomerService.selectWeCustomerList(weCustomer); -// ExcelUtil util = new ExcelUtil(WeCustomer.class); -// return util.exportExcel(list, "customer"); -// } + /** + * 导出企业微信客户列表 + */ + @PreAuthorize("@ss.hasPermi('wecom:customer:export')") + @Log(title = "企业微信客户", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(WeCustomer weCustomer) + { + List list = weCustomerService.selectWeCustomerList(weCustomer); + ExcelUtil util = new ExcelUtil(WeCustomer.class); + return util.exportExcel(list, "customer"); + } /** * 获取企业微信客户详细信息 */ @PreAuthorize("@ss.hasPermi('customerManage:customer:view')") - @GetMapping(value = "/{id}") - public AjaxResult getInfo(@PathVariable("id") Long id) + @GetMapping(value = "/{externalUserId}") + public AjaxResult getInfo(@PathVariable("externalUserId") String externalUserId) { - return AjaxResult.success(weCustomerService.selectWeCustomerById(id)); + return AjaxResult.success(weCustomerService.selectWeCustomerById(externalUserId)); } @@ -108,9 +111,18 @@ public class WeCustomerController extends BaseController @Log(title = "企业微信客户同步接口", businessType = BusinessType.DELETE) @GetMapping("/synchWeCustomer") public AjaxResult synchWeCustomer(){ - - weCustomerService.synchWeCustomer(); - + SecurityContext securityContext = SecurityContextHolder.getContext(); + try { + Threads.SINGLE_THREAD_POOL.execute(new Runnable() { + @Override + public void run() { + SecurityContextHolder.setContext(securityContext); + weCustomerService.synchWeCustomer(); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } return AjaxResult.success(WeConstans.SYNCH_TIP); } diff --git a/linkwe-admin/src/main/resources/application.yml b/linkwe-admin/src/main/resources/application.yml index 21d9b656..97135af7 100644 --- a/linkwe-admin/src/main/resources/application.yml +++ b/linkwe-admin/src/main/resources/application.yml @@ -44,7 +44,7 @@ spring: messages: # 国际化资源文件路径 basename: i18n/messages - profiles: + profiles: active: druid # 文件上传 servlet: @@ -65,7 +65,7 @@ spring: # 端口,默认为6379 port: 6379 # 密码 - password: + password: # 连接超时时间 timeout: 10s lettuce: @@ -105,11 +105,11 @@ mybatis-plus: # configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 -pagehelper: +pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true - params: count=countSql + params: count=countSql # Swagger配置 swagger: @@ -119,7 +119,7 @@ swagger: pathMapping: # 防止XSS攻击 -xss: +xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) @@ -148,6 +148,7 @@ wecome: - /externalcontact/edit_corp_tag - /externalcontact/list - /externalcontact/get + - /externalcontact/batch/get_by_user - /externalcontact/groupchat/list - /externalcontact/groupchat/get - /externalcontact/mark_tag diff --git a/linkwe-common/src/main/java/com/linkwechat/common/constant/WeConstans.java b/linkwe-common/src/main/java/com/linkwechat/common/constant/WeConstans.java index 6f6259a5..c626bab9 100644 --- a/linkwe-common/src/main/java/com/linkwechat/common/constant/WeConstans.java +++ b/linkwe-common/src/main/java/com/linkwechat/common/constant/WeConstans.java @@ -170,5 +170,6 @@ public class WeConstans { public static final String COMMA = ","; - + public static final String USER_ID = "userid"; + public static final String CURSOR = "cursor"; } diff --git a/linkwe-common/src/main/java/com/linkwechat/common/utils/Threads.java b/linkwe-common/src/main/java/com/linkwechat/common/utils/Threads.java index ec9257dc..08819b49 100644 --- a/linkwe-common/src/main/java/com/linkwechat/common/utils/Threads.java +++ b/linkwe-common/src/main/java/com/linkwechat/common/utils/Threads.java @@ -1,10 +1,8 @@ package com.linkwechat.common.utils; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,6 +15,17 @@ public class Threads { private static final Logger logger = LoggerFactory.getLogger(Threads.class); + private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors(); + + private static final ThreadFactory NAMED_THREAD_FACTORY = new ThreadFactoryBuilder().setNameFormat("common-pool-%d").build(); + /** + * 创建线程池 + */ + public static final ThreadPoolExecutor SINGLE_THREAD_POOL = new ThreadPoolExecutor(CORE_POOL_SIZE, CORE_POOL_SIZE+1, 10l, TimeUnit.SECONDS, + new LinkedBlockingQueue<>(1024),NAMED_THREAD_FACTORY); + + + /** * sleep等待,单位为毫秒 */ diff --git a/linkwe-framework/src/main/java/com/linkwechat/framework/manager/ShutdownManager.java b/linkwe-framework/src/main/java/com/linkwechat/framework/manager/ShutdownManager.java index 2a74c3c8..07bf773c 100644 --- a/linkwe-framework/src/main/java/com/linkwechat/framework/manager/ShutdownManager.java +++ b/linkwe-framework/src/main/java/com/linkwechat/framework/manager/ShutdownManager.java @@ -1,5 +1,6 @@ package com.linkwechat.framework.manager; +import com.linkwechat.common.utils.Threads; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -30,6 +31,8 @@ public class ShutdownManager { logger.info("====关闭后台任务任务线程池===="); AsyncManager.me().shutdown(); + logger.info("====关闭后台线程池===="); + Threads.shutdownAndAwaitTermination(Threads.SINGLE_THREAD_POOL); } catch (Exception e) { diff --git a/linkwe-ui/src/api/customer/index.js b/linkwe-ui/src/api/customer/index.js index 711b0b10..46d8405d 100644 --- a/linkwe-ui/src/api/customer/index.js +++ b/linkwe-ui/src/api/customer/index.js @@ -17,6 +17,7 @@ const service = config.services.wecom + '/customer' export function getList(params) { return request({ url: service + '/list', + method: 'get', params }) } @@ -84,4 +85,13 @@ export function updateBirthday(data) { method: 'PUT', data }) +} + +// 导出用户 +export function exportCustomer(query) { + return request({ + url: service + '/export', + method: 'get', + params: query + }) } \ No newline at end of file diff --git a/linkwe-ui/src/views/customerManage/customer.vue b/linkwe-ui/src/views/customerManage/customer.vue index a158ce75..077c2805 100644 --- a/linkwe-ui/src/views/customerManage/customer.vue +++ b/linkwe-ui/src/views/customerManage/customer.vue @@ -15,7 +15,7 @@ export default { pageNum: 1, pageSize: 10, name: "", // "客户名称", - userId: "", // "添加人id", + userIds: "", // "添加人id", tagIds: "", // "标签id,多个标签,id使用逗号隔开", beginTime: "", // "开始时间", endTime: "", // "结束时间" @@ -96,6 +96,9 @@ export default { if (this.dateRange[0]) { this.query.beginTime = this.dateRange[0]; this.query.endTime = this.dateRange[1]; + }else { + this.query.beginTime = ""; + this.query.endTime = ""; } page && (this.query.pageNum = page); this.loading = true; @@ -173,11 +176,30 @@ export default { api.sync().then(() => { loading.close(); this.msgSuccess("后台开始同步数据,请稍后关注进度"); - }); + }).catch(fail => { + loading.close(); + console.log(fail) + });; + }, + /** 导出按钮操作 */ + exportCustomer() { + const queryParams = this.query; + this.$confirm("是否确认导出所有客户数据项?", "警告", { + confirmButtonText: "确定", + cancelButtonText: "取消", + type: "warning", + }) + .then(function () { + return api.exportCustomer(queryParams); + }) + .then((response) => { + this.download(response.msg); + }) + .catch(function () {}); }, selectedUser(list) { this.queryUser = list; - this.query.userId = list.map((d) => d.id) + ""; + this.query.userIds = list.map((d) => d.userId) + ""; }, submitSelectTag(formName) { if (this.tagDialogType.type === "query") { @@ -267,7 +289,7 @@ export default { 导出列表 diff --git a/linkwe-wecom/src/main/java/com/linkwechat/wecom/client/WeCustomerClient.java b/linkwe-wecom/src/main/java/com/linkwechat/wecom/client/WeCustomerClient.java index eb221c73..fff0ae5d 100644 --- a/linkwe-wecom/src/main/java/com/linkwechat/wecom/client/WeCustomerClient.java +++ b/linkwe-wecom/src/main/java/com/linkwechat/wecom/client/WeCustomerClient.java @@ -10,6 +10,8 @@ import com.linkwechat.wecom.domain.dto.customer.ExternalUserDetail; import com.linkwechat.wecom.domain.dto.customer.ExternalUserList; import com.linkwechat.wecom.domain.dto.customer.FollowUserList; +import java.util.Map; + /** * @description: 获取配置客户联系人功能的成员 * @author: HaoN @@ -42,6 +44,14 @@ public interface WeCustomerClient { @Request(url = "/externalcontact/get") ExternalUserDetail get(@Query("external_userid") String externalUserid); + /** + * 根据企业成员id批量获取客户详情 + * @param query + * @return + */ + @Request(url = "/externalcontact/batch/get_by_user", type = "POST") + ExternalUserList getByUser(@DataObject Map query); + /** * 修改客户备注信息 diff --git a/linkwe-wecom/src/main/java/com/linkwechat/wecom/domain/WeCustomer.java b/linkwe-wecom/src/main/java/com/linkwechat/wecom/domain/WeCustomer.java index 97f1f213..0a203834 100644 --- a/linkwe-wecom/src/main/java/com/linkwechat/wecom/domain/WeCustomer.java +++ b/linkwe-wecom/src/main/java/com/linkwechat/wecom/domain/WeCustomer.java @@ -7,6 +7,8 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; +import com.linkwechat.common.annotation.Excel; +import com.linkwechat.common.annotation.Excels; import com.linkwechat.common.core.domain.BaseEntity; import com.linkwechat.common.utils.SnowFlakeUtil; import lombok.AllArgsConstructor; @@ -29,7 +31,7 @@ import javax.validation.constraints.NotBlank; @AllArgsConstructor @NoArgsConstructor @TableName("we_customer") -public class WeCustomer +public class WeCustomer extends BaseEntity { private static final long serialVersionUID = 1L; @@ -40,15 +42,18 @@ public class WeCustomer private String externalUserid; /** 外部联系人名称 */ + @Excel(name = "客户") private String name; /** 外部联系人头像 */ private String avatar; /** 外部联系人的类型,1表示该外部联系人是微信用户,2表示该外部联系人是企业微信用户 */ + @Excel(name = "客户类型", readConverterExp = "1=微信,2=企业微信") private Integer type; /** 外部联系人性别 0-未知 1-男性 2-女性 */ + @Excel(name = "性别", readConverterExp = "0=未知,1=男性,2=女性") private Integer gender; /** 外部联系人在微信开放平台的唯一身份标识,通过此字段企业可将外部联系人与公众号/小程序用户关联起来。 */ @@ -60,6 +65,7 @@ public class WeCustomer /** 客户企业简称 */ + @Excel(name = "公司名称") private String corpName; /** 客户企业全称 */ @@ -72,8 +78,12 @@ public class WeCustomer @TableField(exist = false) private List weFlowerCustomerRels; + /** 添加人id */ + @TableField(exist = false) + private String userIds; - - + /** 标签 */ + @TableField(exist = false) + private String tagIds; } diff --git a/linkwe-wecom/src/main/java/com/linkwechat/wecom/domain/dto/customer/ExternalUserDetail.java b/linkwe-wecom/src/main/java/com/linkwechat/wecom/domain/dto/customer/ExternalUserDetail.java index 2b646f75..b7ed0d83 100644 --- a/linkwe-wecom/src/main/java/com/linkwechat/wecom/domain/dto/customer/ExternalUserDetail.java +++ b/linkwe-wecom/src/main/java/com/linkwechat/wecom/domain/dto/customer/ExternalUserDetail.java @@ -21,6 +21,7 @@ public class ExternalUserDetail extends WeResultDto { /** 客户联系人 */ private List follow_user; + private List follow_info; @Data @@ -68,4 +69,24 @@ public class ExternalUserDetail extends WeResultDto { private List tags; } + @Data + public class FollowInfo{ + /**该成员对此外部联系人的备注*/ + private String remark; + /**该成员对此外部联系人的描述*/ + private String description; + /**该成员添加此外部联系人的时间*/ + private long createtime; + /**该成员对此客户备注的企业名称*/ + private String remark_company; + /**该成员对此客户备注的手机号码*/ + private String[] remark_mobiles; + /**该成员添加此客户的来源*/ + private Integer add_way; + /**发起添加的userid,如果成员主动添加,为成员的userid;如果是客户主动添加,则为客户的外部联系人userid;如果是内部成员共享/管理员分配,则为对应的成员/管理员userid*/ + private String oper_userid; + /**标签**/ + private String[] tag_id; + } + } diff --git a/linkwe-wecom/src/main/java/com/linkwechat/wecom/domain/dto/customer/ExternalUserList.java b/linkwe-wecom/src/main/java/com/linkwechat/wecom/domain/dto/customer/ExternalUserList.java index 55571d47..ef5cd3e9 100644 --- a/linkwe-wecom/src/main/java/com/linkwechat/wecom/domain/dto/customer/ExternalUserList.java +++ b/linkwe-wecom/src/main/java/com/linkwechat/wecom/domain/dto/customer/ExternalUserList.java @@ -3,6 +3,8 @@ package com.linkwechat.wecom.domain.dto.customer; import com.linkwechat.wecom.domain.dto.WeResultDto; import lombok.Data; +import java.util.List; + /** * @description: 客户列表 * @author: HaoN @@ -11,4 +13,6 @@ import lombok.Data; @Data public class ExternalUserList extends WeResultDto { private String[] external_userid; + private List external_contact_list; + private String next_cursor; } diff --git a/linkwe-wecom/src/main/java/com/linkwechat/wecom/mapper/WeCustomerMapper.java b/linkwe-wecom/src/main/java/com/linkwechat/wecom/mapper/WeCustomerMapper.java index 8484e082..cd4bd243 100644 --- a/linkwe-wecom/src/main/java/com/linkwechat/wecom/mapper/WeCustomerMapper.java +++ b/linkwe-wecom/src/main/java/com/linkwechat/wecom/mapper/WeCustomerMapper.java @@ -18,10 +18,10 @@ public interface WeCustomerMapper extends BaseMapper /** * 查询企业微信客户 * - * @param id 企业微信客户ID + * @param externalUserId 企业微信客户ID * @return 企业微信客户 */ - public WeCustomer selectWeCustomerById(Long id); + public WeCustomer selectWeCustomerById(String externalUserId); /** * 查询企业微信客户列表 @@ -50,18 +50,18 @@ public interface WeCustomerMapper extends BaseMapper /** * 删除企业微信客户 * - * @param id 企业微信客户ID + * @param externalUserId 企业微信客户ID * @return 结果 */ - public int deleteWeCustomerById(Long id); + public int deleteWeCustomerById(String externalUserId); /** * 批量删除企业微信客户 * - * @param ids 需要删除的数据ID + * @param externalUserIds 需要删除的数据ID * @return 结果 */ - public int deleteWeCustomerByIds(Long[] ids); + public int deleteWeCustomerByIds(String[] externalUserIds); /** diff --git a/linkwe-wecom/src/main/java/com/linkwechat/wecom/service/IWeCustomerService.java b/linkwe-wecom/src/main/java/com/linkwechat/wecom/service/IWeCustomerService.java index 1a289a31..55fb47dd 100644 --- a/linkwe-wecom/src/main/java/com/linkwechat/wecom/service/IWeCustomerService.java +++ b/linkwe-wecom/src/main/java/com/linkwechat/wecom/service/IWeCustomerService.java @@ -19,10 +19,19 @@ public interface IWeCustomerService extends IService /** * 查询企业微信客户 * - * @param id 企业微信客户ID + * @param externalUserId 企业微信客户ID * @return 企业微信客户 */ - public WeCustomer selectWeCustomerById(Long id); + public WeCustomer selectWeCustomerById(String externalUserId); + + /** + * 新增/修改企业微信客户 + * + * @param weCustomer 企业微信客户 + * @return 修改结果 + */ + @Override + public boolean saveOrUpdate(WeCustomer weCustomer); /** * 查询企业微信客户列表 diff --git a/linkwe-wecom/src/main/java/com/linkwechat/wecom/service/impl/WeAccessTokenServiceImpl.java b/linkwe-wecom/src/main/java/com/linkwechat/wecom/service/impl/WeAccessTokenServiceImpl.java index 5020cb09..69723b88 100644 --- a/linkwe-wecom/src/main/java/com/linkwechat/wecom/service/impl/WeAccessTokenServiceImpl.java +++ b/linkwe-wecom/src/main/java/com/linkwechat/wecom/service/impl/WeAccessTokenServiceImpl.java @@ -96,6 +96,7 @@ public class WeAccessTokenServiceImpl implements IWeAccessTokenService { if(StringUtils.isNotEmpty(token)){ redisCache.setCacheObject(accessTokenKey,token,expires_in.intValue(), TimeUnit.SECONDS); + weAccessToken = token; } } diff --git a/linkwe-wecom/src/main/java/com/linkwechat/wecom/service/impl/WeCustomerServiceImpl.java b/linkwe-wecom/src/main/java/com/linkwechat/wecom/service/impl/WeCustomerServiceImpl.java index 46f9e939..6df61c97 100644 --- a/linkwe-wecom/src/main/java/com/linkwechat/wecom/service/impl/WeCustomerServiceImpl.java +++ b/linkwe-wecom/src/main/java/com/linkwechat/wecom/service/impl/WeCustomerServiceImpl.java @@ -7,13 +7,18 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.linkwechat.common.constant.WeConstans; import com.linkwechat.common.utils.SecurityUtils; import com.linkwechat.common.utils.SnowFlakeUtil; +import com.linkwechat.common.utils.StringUtils; +import com.linkwechat.common.utils.Threads; import com.linkwechat.common.utils.bean.BeanUtils; import com.linkwechat.wecom.client.WeCropTagClient; import com.linkwechat.wecom.client.WeCustomerClient; import com.linkwechat.wecom.client.WeUserClient; import com.linkwechat.wecom.domain.*; import com.linkwechat.wecom.domain.dto.AllocateWeCustomerDto; -import com.linkwechat.wecom.domain.dto.customer.*; +import com.linkwechat.wecom.domain.dto.customer.CutomerTagEdit; +import com.linkwechat.wecom.domain.dto.customer.ExternalUserDetail; +import com.linkwechat.wecom.domain.dto.customer.ExternalUserList; +import com.linkwechat.wecom.domain.dto.customer.FollowUserList; import com.linkwechat.wecom.domain.dto.tag.WeCropGroupTagDto; import com.linkwechat.wecom.domain.dto.tag.WeCropGroupTagListDto; import com.linkwechat.wecom.domain.dto.tag.WeCropTagDto; @@ -23,21 +28,23 @@ import com.linkwechat.wecom.domain.vo.WeMakeCustomerTag; import com.linkwechat.wecom.mapper.WeCustomerMapper; import com.linkwechat.wecom.service.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * 企业微信客户Service业务层处理 - * + * * @author ruoyi * @date 2020-09-13 */ @Service -public class WeCustomerServiceImpl extends ServiceImpl implements IWeCustomerService -{ +public class WeCustomerServiceImpl extends ServiceImpl implements IWeCustomerService { @Autowired private WeCustomerMapper weCustomerMapper; @@ -72,38 +79,46 @@ public class WeCustomerServiceImpl extends ServiceImpl selectWeCustomerList(WeCustomer weCustomer) - { + public List selectWeCustomerList(WeCustomer weCustomer) { return weCustomerMapper.selectWeCustomerList(weCustomer); } - /** * 客户同步接口 + * * @return */ @Override @@ -112,164 +127,171 @@ public class WeCustomerServiceImpl extends ServiceImpl{ - - //获取指定联系人对应的客户 - ExternalUserList externalUsers = weCustomerClient.list(k); - if(WeConstans.WE_SUCCESS_CODE.equals(externalUsers.getErrcode()) - || WeConstans.NOT_EXIST_CONTACT.equals(externalUsers.getErrcode()) - && ArrayUtil.isNotEmpty(externalUsers.getExternal_userid())){ - - Arrays.asList(externalUsers.getExternal_userid()).forEach(v->{ - - //获取指定客户的详情 - ExternalUserDetail externalUserDetail = weCustomerClient.get(v); - - if(WeConstans.WE_SUCCESS_CODE.equals(externalUserDetail.getErrcode())){ - //客户入库 - WeCustomer weCustomer=new WeCustomer(); - BeanUtils.copyPropertiesignoreOther( externalUserDetail.getExternal_contact(),weCustomer); - this.saveOrUpdate(weCustomer); - - //客户与通讯录客户关系 - List weTags=new ArrayList<>(); - List weGroups=new ArrayList<>(); - List weFlowerCustomerTagRels=new ArrayList<>(); - List weFlowerCustomerRel=new ArrayList<>(); - externalUserDetail.getFollow_user().stream().forEach(kk->{ + .stream().forEach(k -> { + try { + Threads.SINGLE_THREAD_POOL.execute(new Runnable() { + @Override + public void run() { + SecurityContextHolder.setContext(securityContext); + weFlowerCustomerHandle(k); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + } + + /** + * 客户同步业务处理 + * + * @param userId 开通权限的企业成员id + */ + private void weFlowerCustomerHandle(String userId) { + List list = new ArrayList<>(); + getByUser(userId, null, list); + list.forEach(userDetail -> { + //客户入库 + WeCustomer weCustomer = new WeCustomer(); + BeanUtils.copyPropertiesignoreOther(userDetail.getExternal_contact(), weCustomer); + this.saveOrUpdate(weCustomer); + + //客户与通讯录客户关系 + List weTags = new ArrayList<>(); + List weGroups = new ArrayList<>(); + List weFlowerCustomerTagRels = new ArrayList<>(); + List weFlowerCustomerRel = new ArrayList<>(); + userDetail.getFollow_info().stream().forEach(kk -> { // WeFlowerCustomerRel weFlowerCustomerRelOne=new WeFlowerCustomerRel(); // BeanUtils.copyPropertiesignoreOther(kk,weFlowerCustomerRelOne); - Long weFlowerCustomerRelId=SnowFlakeUtil.nextId(); + Long weFlowerCustomerRelId = SnowFlakeUtil.nextId(); // weFlowerCustomerRelOne.setId(weFlowerCustomerRelId); // weFlowerCustomerRelOne.setExternalUserid(weCustomer.getExternalUserid()); - weFlowerCustomerRel.add(WeFlowerCustomerRel.builder() - .id(weFlowerCustomerRelId) - .userId(kk.getUserid()) - .description(kk.getDescription()) - .remarkCorpName(kk.getRemark_company()) - .remarkMobiles(kk.getRemark_mobiles()) - .operUserid(kk.getOper_userid()) - .addWay(kk.getAdd_way()) - .externalUserid(weCustomer.getExternalUserid()) - .createTime(new Date(kk.getCreatetime() * 1000L)) - .build()); - - List tags = kk.getTags(); - if(CollectionUtil.isNotEmpty(tags)){ - - //获取相关标签组 - WeCropGroupTagListDto weCropGroupTagListDto = weCropTagClient.getCorpTagListByTagIds(WeFindCropTagParam.builder() - .tag_id(ArrayUtil.toArray(tags.stream().map(ExternalUserTag::getTag_id).collect(Collectors.toList()), String.class)) - .build()); - - if(weCropGroupTagListDto.getErrcode().equals(WeConstans.WE_SUCCESS_CODE)){ - List tagGroups = weCropGroupTagListDto.getTag_group(); - if(CollectionUtil.isNotEmpty(tagGroups)){ - tagGroups.stream().forEach(tagGroup->{ - weGroups.add( - WeTagGroup.builder() - .groupId(tagGroup.getGroup_id()) - .gourpName(tagGroup.getGroup_name()) - .createBy(SecurityUtils.getUsername()) - .build() - ); - - List weCropTagDtos= tagGroup.getTag(); - - if(CollectionUtil.isNotEmpty(weCropTagDtos)){ - Set tagIdsSet = weCropTagDtos.stream().map(WeCropTagDto::getId).collect(Collectors.toSet()); - - tags.stream().forEach(tag->{ - - if(tagIdsSet.contains(tag.getTag_id())){ - - weTags.add( - WeTag.builder() - .groupId(tagGroup.getGroup_id()) - .tagId(tag.getTag_id()) - .name(tag.getTag_name()) - .build() - ); - - weFlowerCustomerTagRels.add( - WeFlowerCustomerTagRel.builder() - .flowerCustomerRelId(weFlowerCustomerRelId) - .tagId(tag.getTag_id()) - .createTime(new Date()) - .build() - ); - - - } - - - - }); - - - } - - - }); - - - + weFlowerCustomerRel.add(WeFlowerCustomerRel.builder() + .id(weFlowerCustomerRelId) + .userId(userId) + .description(kk.getDescription()) + .remarkCorpName(kk.getRemark_company()) + .remarkMobiles(kk.getRemark_mobiles()) + .operUserid(kk.getOper_userid()) + .addWay(kk.getAdd_way()) + .externalUserid(weCustomer.getExternalUserid()) + .createTime(new Date(kk.getCreatetime() * 1000L)) + .build()); + + List tags = Stream.of(kk.getTag_id()).collect(Collectors.toList()); + if (CollectionUtil.isNotEmpty(tags)) { + + //获取相关标签组 + WeCropGroupTagListDto weCropGroupTagListDto = weCropTagClient.getCorpTagListByTagIds(WeFindCropTagParam.builder() + .tag_id(kk.getTag_id()) + .build()); + + if (weCropGroupTagListDto.getErrcode().equals(WeConstans.WE_SUCCESS_CODE)) { + List tagGroups = weCropGroupTagListDto.getTag_group(); + if (CollectionUtil.isNotEmpty(tagGroups)) { + tagGroups.stream().forEach(tagGroup -> { + weGroups.add( + WeTagGroup.builder() + .groupId(tagGroup.getGroup_id()) + .gourpName(tagGroup.getGroup_name()) + .createBy(SecurityUtils.getUsername()) + .build() + ); + List weCropTagDtos = tagGroup.getTag(); + if (CollectionUtil.isNotEmpty(weCropTagDtos)) { + Map map = weCropTagDtos.stream().collect(Collectors.toMap(WeCropTagDto::getId, WeCropTagDto::getName)); + tags.forEach(tag -> { + if (map.containsKey(tag)) { + weTags.add( + WeTag.builder() + .groupId(tagGroup.getGroup_id()) + .tagId(tag) + .name(map.get(tag)) + .build() + ); + + weFlowerCustomerTagRels.add( + WeFlowerCustomerTagRel.builder() + .flowerCustomerRelId(weFlowerCustomerRelId) + .tagId(tag) + .createTime(new Date()) + .build() + ); } - } - - + }); } - }); - List weFlowerCustomerRels = iWeFlowerCustomerRelService.list(new LambdaQueryWrapper() - .eq(WeFlowerCustomerRel::getExternalUserid, weCustomer.getExternalUserid())); - - if(CollectionUtil.isNotEmpty(weFlowerCustomerRels)){ - List weFlowerCustomerRelIds = weFlowerCustomerRels.stream().map(WeFlowerCustomerRel::getId).collect(Collectors.toList()); - iWeFlowerCustomerTagRelService.remove( - new LambdaQueryWrapper().in(WeFlowerCustomerTagRel::getFlowerCustomerRelId, - weFlowerCustomerRelIds) - ); - iWeFlowerCustomerRelService.removeByIds( - weFlowerCustomerRelIds - ); - } - - - iWeFlowerCustomerRelService.saveBatch(weFlowerCustomerRel); + }); - //设置标签跟客户关系,标签和标签组,saveOrUpdate,建立标签与添加人关系 - if(CollectionUtil.isNotEmpty(weTags)&&CollectionUtil.isNotEmpty(weGroups)){ - iWeTagService.saveOrUpdateBatch(weTags); - iWeTagGroupService.saveOrUpdateBatch(weGroups); - iWeFlowerCustomerTagRelService.saveOrUpdateBatch(weFlowerCustomerTagRels); - } } + } + } + }); + List weFlowerCustomerRels = iWeFlowerCustomerRelService.list(new LambdaQueryWrapper() + .eq(WeFlowerCustomerRel::getExternalUserid, weCustomer.getExternalUserid())); + + if (CollectionUtil.isNotEmpty(weFlowerCustomerRels)) { + List weFlowerCustomerRelIds = weFlowerCustomerRels.stream().map(WeFlowerCustomerRel::getId).collect(Collectors.toList()); + iWeFlowerCustomerTagRelService.remove( + new LambdaQueryWrapper().in(WeFlowerCustomerTagRel::getFlowerCustomerRelId, + weFlowerCustomerRelIds) + ); - }); + iWeFlowerCustomerRelService.removeByIds( + weFlowerCustomerRelIds + ); + } - } - }); + iWeFlowerCustomerRelService.saveBatch(weFlowerCustomerRel); + //设置标签跟客户关系,标签和标签组,saveOrUpdate,建立标签与添加人关系 + if (CollectionUtil.isNotEmpty(weTags) && CollectionUtil.isNotEmpty(weGroups)) { + iWeTagService.saveOrUpdateBatch(weTags); + iWeTagGroupService.saveOrUpdateBatch(weGroups); + iWeFlowerCustomerTagRelService.saveOrUpdateBatch(weFlowerCustomerTagRels); + } + }); + } + /** + * 批量获取客户详情 + * + * @param userId 企业成员的userid + * @param nextCursor 用于分页查询的游标 + * @param list 返回结果 + */ + private void getByUser(String userId, String nextCursor, List list) { + Map query = new HashMap<>(16); + query.put(WeConstans.USER_ID, userId); + query.put(WeConstans.CURSOR, nextCursor); + ExternalUserList externalUserList = weCustomerClient.getByUser(query); + if (WeConstans.WE_SUCCESS_CODE.equals(externalUserList.getErrcode()) + || WeConstans.NOT_EXIST_CONTACT.equals(externalUserList.getErrcode()) + && ArrayUtil.isNotEmpty(externalUserList.getExternal_contact_list())) { + list.addAll(externalUserList.getExternal_contact_list()); + if (StringUtils.isNotEmpty(externalUserList.getNext_cursor())) { + getByUser(userId, externalUserList.getNext_cursor(), list); + } } - } /** * 分配离职员工客户 + * * @param weLeaveUserInfoAllocateVo */ @Override @@ -279,12 +301,11 @@ public class WeCustomerServiceImpl extends ServiceImpl weFlowerCustomerRels = iWeFlowerCustomerRelService.list(new LambdaQueryWrapper() .eq(WeFlowerCustomerRel::getUserId, weLeaveUserInfoAllocateVo.getHandoverUserid())); - if(CollectionUtil.isNotEmpty(weFlowerCustomerRels)){ - + if (CollectionUtil.isNotEmpty(weFlowerCustomerRels)) { - List weAllocateCustomers=new ArrayList<>(); - weFlowerCustomerRels.stream().forEach(k->{ + List weAllocateCustomers = new ArrayList<>(); + weFlowerCustomerRels.stream().forEach(k -> { k.setUserId(weLeaveUserInfoAllocateVo.getTakeoverUserid()); weAllocateCustomers.add( WeAllocateCustomer.builder() @@ -300,12 +321,12 @@ public class WeCustomerServiceImpl extends ServiceImpl{ + weAllocateCustomers.stream().forEach(v -> { weUserClient.allocateCustomer(AllocateWeCustomerDto.builder() .external_userid(v.getExternalUserid()) .handover_userid(v.getHandoverUserid()) @@ -318,8 +339,6 @@ public class WeCustomerServiceImpl extends ServiceImpl flowerCustomerRels = iWeFlowerCustomerRelService.list(new LambdaQueryWrapper() .eq(WeFlowerCustomerRel::getExternalUserid, weMakeCustomerTag.getExternalUserid())); - if(CollectionUtil.isNotEmpty(flowerCustomerRels)){ - + if (CollectionUtil.isNotEmpty(flowerCustomerRels)) { List addTags = weMakeCustomerTag.getAddTag(); - - if(CollectionUtil.isNotEmpty(addTags)){ + if (CollectionUtil.isNotEmpty(addTags)) { addTags.removeAll(Collections.singleton(null)); - List tagRels=new ArrayList<>(); - - List cutomerTagEdits=new ArrayList<>(); - flowerCustomerRels.stream().forEach(customer->{ - CutomerTagEdit cutomerTagEdit = CutomerTagEdit.builder() - .userid(customer.getUserId()) - .external_userid(customer.getExternalUserid()) - .build(); - List tags=new ArrayList<>(); - addTags.stream().forEach(tag->{ - tags.add(tag.getTagId()); - tagRels.add( - WeFlowerCustomerTagRel.builder() - .flowerCustomerRelId(customer.getId()) - .tagId(tag.getTagId()) - .createTime(new Date()) - .build() - ); - }); - - cutomerTagEdit.setAdd_tag(ArrayUtil.toArray(tags,String.class)); - cutomerTagEdits.add(cutomerTagEdit); + List tagRels = new ArrayList<>(); + + List cutomerTagEdits = new ArrayList<>(); + flowerCustomerRels.stream().forEach(customer -> { + CutomerTagEdit cutomerTagEdit = CutomerTagEdit.builder() + .userid(customer.getUserId()) + .external_userid(customer.getExternalUserid()) + .build(); + List tags = new ArrayList<>(); + addTags.stream().forEach(tag -> { + tags.add(tag.getTagId()); + tagRels.add( + WeFlowerCustomerTagRel.builder() + .flowerCustomerRelId(customer.getId()) + .tagId(tag.getTagId()) + .createTime(new Date()) + .build() + ); }); - if(iWeFlowerCustomerTagRelService.saveOrUpdateBatch(tagRels)){ - if(CollectionUtil.isNotEmpty(cutomerTagEdits)){ - cutomerTagEdits.stream().forEach(k->{ + cutomerTagEdit.setAdd_tag(ArrayUtil.toArray(tags, String.class)); + cutomerTagEdits.add(cutomerTagEdit); + }); + + if (iWeFlowerCustomerTagRelService.saveOrUpdateBatch(tagRels)) { + if (CollectionUtil.isNotEmpty(cutomerTagEdits)) { + cutomerTagEdits.stream().forEach(k -> { weCustomerClient.makeCustomerLabel( k ); @@ -383,12 +401,12 @@ public class WeCustomerServiceImpl extends ServiceImpl addTags = weMakeCustomerTag.getAddTag(); - if(CollectionUtil.isNotEmpty(addTags)){ + if (CollectionUtil.isNotEmpty(addTags)) { //获取当前客户需要移除的标签 List removeTag = iWeFlowerCustomerTagRelService.list(new LambdaQueryWrapper() @@ -411,15 +429,15 @@ public class WeCustomerServiceImpl extends ServiceImpl flowerCustomerRels = iWeFlowerCustomerRelService.list(new LambdaQueryWrapper() .eq(WeFlowerCustomerRel::getExternalUserid, weMakeCustomerTag.getExternalUserid())); - if(CollectionUtil.isNotEmpty(flowerCustomerRels) ){ + if (CollectionUtil.isNotEmpty(flowerCustomerRels)) { - if(iWeFlowerCustomerTagRelService.remove( + if (iWeFlowerCustomerTagRelService.remove( new LambdaQueryWrapper() .in(WeFlowerCustomerTagRel::getFlowerCustomerRelId, flowerCustomerRels.stream().map(WeFlowerCustomerRel::getId).collect(Collectors.toList())) .in(WeFlowerCustomerTagRel::getTagId, removeTag.stream().map(WeFlowerCustomerTagRel::getTagId).collect(Collectors.toList())) - )){ + )) { - flowerCustomerRels.stream().forEach(k->{ + flowerCustomerRels.stream().forEach(k -> { weCustomerClient.makeCustomerLabel( CutomerTagEdit.builder() .external_userid(k.getExternalUserid()) @@ -439,14 +457,12 @@ public class WeCustomerServiceImpl extends ServiceImpl - select id, external_userid, name, avatar, type, gender, unionid, birthday, corp_name, corp_full_name, position from we_customer + select external_userid, name, avatar, type, gender, unionid, birthday, corp_name, corp_full_name, position from we_customer - - where id = #{id} + where external_userid = #{externalUserId} insert into we_customer - id, external_userid, name, avatar, @@ -96,7 +129,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" position, - #{id}, #{externalUserid}, #{name}, #{avatar}, @@ -124,17 +156,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" corp_full_name = #{corpFullName}, position = #{position}, - where id = #{id} + where external_userid = #{externalUserid} - - delete from we_customer where id = #{id} + + delete from we_customer where external_userid = #{externalUserId} - - delete from we_customer where id in - - #{id} + + delete from we_customer where external_userid in + + #{item} -- GitLab