Browse Source

update
诚泰财险
1.报价相关

wks 11 months ago
parent
commit
a96a9f7edf
40 changed files with 1785 additions and 2 deletions
  1. 1 1
      gateway/src/main/resources/application-dev.yml
  2. 7 0
      pom.xml
  3. 2 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/impl/ChengTaiCrawlerQuoteProcessServiceImpl.java
  4. 3 1
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/impl/ChengTaiCrawlerRequestImpl.java
  5. 8 0
      tenant/organization/pom.xml
  6. 51 0
      tenant/organization/src/main/java/com/jzg/organization/config/WeComConfig.java
  7. 123 0
      tenant/organization/src/main/java/com/jzg/organization/controller/WechatCustomerServiceManageController.java
  8. 106 0
      tenant/organization/src/main/java/com/jzg/organization/entity/SysHolidays.java
  9. 87 0
      tenant/organization/src/main/java/com/jzg/organization/entity/WechatCustomerService.java
  10. 68 0
      tenant/organization/src/main/java/com/jzg/organization/entity/WechatCustomerServiceDuty.java
  11. 91 0
      tenant/organization/src/main/java/com/jzg/organization/entity/WechatCustomerServiceRecording.java
  12. 46 0
      tenant/organization/src/main/java/com/jzg/organization/entity/dto/WechatCustomerServicePageDto.java
  13. 36 0
      tenant/organization/src/main/java/com/jzg/organization/entity/vo/WeComDeptVo.java
  14. 19 0
      tenant/organization/src/main/java/com/jzg/organization/entity/vo/WeComUserVo.java
  15. 24 0
      tenant/organization/src/main/java/com/jzg/organization/entity/vo/WechatCustomerServiceDutyRulesVo.java
  16. 46 0
      tenant/organization/src/main/java/com/jzg/organization/entity/vo/WechatCustomerServiceDutyVo.java
  17. 56 0
      tenant/organization/src/main/java/com/jzg/organization/entity/vo/WechatCustomerServicePageVo.java
  18. 25 0
      tenant/organization/src/main/java/com/jzg/organization/entity/vo/WechatCustomerServiceQueryVo.java
  19. 69 0
      tenant/organization/src/main/java/com/jzg/organization/entity/vo/WechatCustomerServiceVo.java
  20. 16 0
      tenant/organization/src/main/java/com/jzg/organization/mapper/SysHolidaysMapper.java
  21. 16 0
      tenant/organization/src/main/java/com/jzg/organization/mapper/WechatCustomerServiceDutyMapper.java
  22. 28 0
      tenant/organization/src/main/java/com/jzg/organization/mapper/WechatCustomerServiceMapper.java
  23. 16 0
      tenant/organization/src/main/java/com/jzg/organization/mapper/WechatCustomerServiceRecordingMapper.java
  24. 16 0
      tenant/organization/src/main/java/com/jzg/organization/service/ISysHolidaysService.java
  25. 37 0
      tenant/organization/src/main/java/com/jzg/organization/service/IWechatCustomerServiceDutyService.java
  26. 16 0
      tenant/organization/src/main/java/com/jzg/organization/service/IWechatCustomerServiceRecordingService.java
  27. 94 0
      tenant/organization/src/main/java/com/jzg/organization/service/IWechatCustomerServiceService.java
  28. 26 0
      tenant/organization/src/main/java/com/jzg/organization/service/SysUserService.java
  29. 84 0
      tenant/organization/src/main/java/com/jzg/organization/service/WechatCustomerServiceManageService.java
  30. 20 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysHolidaysServiceImpl.java
  31. 10 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserServiceImpl.java
  32. 80 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/WechatCustomerServiceDutyServiceImpl.java
  33. 303 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/WechatCustomerServiceManageServiceImpl.java
  34. 20 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/WechatCustomerServiceRecordingServiceImpl.java
  35. 87 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/WechatCustomerServiceServiceImpl.java
  36. 3 0
      tenant/organization/src/main/resources/application.yml
  37. 5 0
      tenant/organization/src/main/resources/mapper/SysHolidaysMapper.xml
  38. 5 0
      tenant/organization/src/main/resources/mapper/WechatCustomerServiceDutyMapper.xml
  39. 30 0
      tenant/organization/src/main/resources/mapper/WechatCustomerServiceMapper.xml
  40. 5 0
      tenant/organization/src/main/resources/mapper/WechatCustomerServiceRecordingMapper.xml

+ 1 - 1
gateway/src/main/resources/application-dev.yml

@@ -33,7 +33,7 @@ spring:
         - id: tenant_route
           uri: http://localhost:8084/
           predicates:
-            - Path=/tenant/**,/dept/**,/area/**,/dict/**,/userInfo/**,/sysOrganization/**,/activity/**,/message/**,/messageNotice/**,/poster/**,/agreement/**,/pltAgreement/**,/agreementRules/**,/plt/areaLicense/**,/scheme/**,/schemeRules/**,/schemeRulesAttrLink/**,/schemeRulesAttr/**,/schemeRulesDictLable/**,/schemeRulesUndwrt/**,/schemeRulesUndwrtAttrLink/**,/schemeRulesUndwrtAttr/**,/schemeRulesUndwrtDictLable/**,/schemeRulesUndwrtRules/**,/schemeRulesUndwrtRulesAttrLink/**,/schemeRules,/ptlAgreementCost/**,/ptlAgreementCost/**,/ptlAgreementCostExternal/**,/operatorTrajectory/**,/messageTemplate/**,/message/**,/appUser/**,/userBankCard/**,/accountCard/**,/account/**,/amountAuditing/**,/userAccount/**,/receivable/**,/sysDistributionSetting/**
+            - Path=/tenant/**,/dept/**,/area/**,/dict/**,/userInfo/**,/sysOrganization/**,/activity/**,/message/**,/messageNotice/**,/poster/**,/agreement/**,/pltAgreement/**,/agreementRules/**,/plt/areaLicense/**,/scheme/**,/schemeRules/**,/schemeRulesAttrLink/**,/schemeRulesAttr/**,/schemeRulesDictLable/**,/schemeRulesUndwrt/**,/schemeRulesUndwrtAttrLink/**,/schemeRulesUndwrtAttr/**,/schemeRulesUndwrtDictLable/**,/schemeRulesUndwrtRules/**,/schemeRulesUndwrtRulesAttrLink/**,/schemeRules,/ptlAgreementCost/**,/ptlAgreementCost/**,/ptlAgreementCostExternal/**,/operatorTrajectory/**,/messageTemplate/**,/message/**,/appUser/**,/userBankCard/**,/accountCard/**,/account/**,/amountAuditing/**,/userAccount/**,/receivable/**,/sysDistributionSetting/**,/organization/**
 
         - id: summary_route
           uri: http://localhost:9898/

+ 7 - 0
pom.xml

@@ -40,6 +40,7 @@
     <rocketmq.version>2.2.1</rocketmq.version>
     <rocket.version>1.0-SNAPSHOT</rocket.version>
     <seate.version>1.7.0</seate.version>
+    <weixin-java.version>4.7.0</weixin-java.version>
   </properties>
 
 
@@ -240,6 +241,12 @@
         <version>${rocket.version}</version>
       </dependency>
 
+      <dependency>
+        <groupId>com.github.binarywang</groupId>
+        <artifactId>weixin-java-cp</artifactId>
+        <version>${weixin-java.version}</version>
+      </dependency>
+
     </dependencies>
   </dependencyManagement>
 

+ 2 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/impl/ChengTaiCrawlerQuoteProcessServiceImpl.java

@@ -80,6 +80,8 @@ public class ChengTaiCrawlerQuoteProcessServiceImpl implements ChengTaiCrawlerQu
         ChengTaiFindCoreConferInfoByHandleCodeResponse coreConferInfoByHandleCode = chengTaiRequestCrawlerComponent.findCoreConferInfoByHandleCode(saleManVoByDeptCode.getUserCode(), parameters.getAgreementCode(), headers);
         // 步骤四 构造归属信息
 
+
+
     }
 
 

+ 3 - 1
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/impl/ChengTaiCrawlerRequestImpl.java

@@ -63,8 +63,10 @@ public class ChengTaiCrawlerRequestImpl implements ChengTaiCrawlerRequest {
             insuredPerson = chengTaiRequestCrawlerComponent.clientIdentify(insuredPersonInfo, "2", "", httpHeaders);
         }
         // 步骤五 报价
-
         ChengTaiPremiumcaResponse premiumca = chengTaiRequestCrawlerComponent.premiumca(quoteVo, carModel, policyHolder, insuredPerson, actualValue, httpHeaders);
+
+
+
         return null;
     }
 

+ 8 - 0
tenant/organization/pom.xml

@@ -21,6 +21,10 @@
             <artifactId>spring-cloud-starter-openfeign</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>com.jzg</groupId>
@@ -48,6 +52,10 @@
             <version>3.2.0</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.github.binarywang</groupId>
+            <artifactId>weixin-java-cp</artifactId>
+        </dependency>
 
     </dependencies>
     <build>

+ 51 - 0
tenant/organization/src/main/java/com/jzg/organization/config/WeComConfig.java

@@ -0,0 +1,51 @@
+package com.jzg.organization.config;
+
+import me.chanjar.weixin.cp.api.*;
+import me.chanjar.weixin.cp.api.impl.*;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import me.chanjar.weixin.cp.message.WxCpMessageRouter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class WeComConfig {
+
+    @Bean
+    public WxCpService wxCpService() {
+        WxCpDefaultConfigImpl config = new WxCpDefaultConfigImpl();
+        config.setCorpId("wwfe67d19509d43ec5");
+        config.setCorpSecret("_tb5qC-MXxYFUEMaaTEb6D_RmQtadt3UUUuvdYcrklI");
+        config.setToken("hGskYOrv1XnVFtooYsX8Q2PxN");
+        config.setAesKey("cYIzKkyIJQY6wFHUTtamtKiy2uxFynTZOx6VHnvC7vI");
+        WxCpServiceImpl wxCpService = new WxCpServiceImpl();
+        wxCpService.setWxCpConfigStorage(config);
+        return wxCpService;
+    }
+
+    @Bean
+    public WxCpKfService wxCpKfService() {
+        return new WxCpKfServiceImpl(wxCpService());
+    }
+
+    @Bean
+    public WxCpMessageRouter wxCpMessageService() {
+        return new WxCpMessageRouter(wxCpService());
+    }
+
+    @Bean
+    public WxCpMediaService wxCpMediaService() {
+        return new WxCpMediaServiceImpl(wxCpService());
+    }
+
+    @Bean
+    public WxCpDepartmentService wxCpDepartmentService() {
+        return new WxCpDepartmentServiceImpl(wxCpService());
+    }
+
+    @Bean
+    public WxCpUserService wxCpUserService() {
+        return new WxCpUserServiceImpl(wxCpService());
+    }
+
+
+}

+ 123 - 0
tenant/organization/src/main/java/com/jzg/organization/controller/WechatCustomerServiceManageController.java

@@ -0,0 +1,123 @@
+package com.jzg.organization.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.jzg.commons.core.base.BaseController;
+import com.jzg.commons.core.page.HttpResult;
+import com.jzg.organization.entity.vo.*;
+import com.jzg.organization.service.IWechatCustomerServiceDutyService;
+import com.jzg.organization.service.IWechatCustomerServiceService;
+import com.jzg.organization.service.WechatCustomerServiceManageService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 前端控制器
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+@Tag(name = "客服管理")
+@RestController
+@RequestMapping("/organization/wechat/customerService/manage")
+@Validated
+@RequiredArgsConstructor
+public class WechatCustomerServiceManageController {
+
+    private final WechatCustomerServiceManageService wechatCustomerServiceManageService;
+
+    private final IWechatCustomerServiceService wechatCustomerServiceService;
+
+    private final IWechatCustomerServiceDutyService wechatCustomerServiceDutyService;
+
+
+    @GetMapping("/getDeptTree")
+    @Operation(summary = "获取企业微信通讯录部门树", description = "获取企业微信通讯录部门树")
+    public HttpResult<List<WeComDeptVo>> getDeptTree() throws WxErrorException {
+        List<WeComDeptVo> deptByDeptId = wechatCustomerServiceManageService.getDeptByDeptId();
+        return HttpResult.ok(deptByDeptId);
+    }
+
+    @GetMapping("/getDeptUser")
+    @Operation(summary = "通过部门id获取用户列表", description = "通过部门id获取用户列表")
+    public HttpResult<List<WeComUserVo>> getDeptUser() throws WxErrorException {
+        List<WeComUserVo> user = wechatCustomerServiceManageService.getUser();
+        return HttpResult.ok(user);
+    }
+
+    @GetMapping("/getDutyConfig/{customerId}")
+    @Operation(summary = "获取值班配置", description = "获取值班配置")
+    public HttpResult<List<WechatCustomerServiceDutyVo>> getDutyConfig(@PathVariable String customerId) {
+        List<WechatCustomerServiceDutyVo> customerDutyRules = wechatCustomerServiceDutyService.getCustomerServiceDutyRules(customerId);
+        return HttpResult.ok(customerDutyRules);
+    }
+
+    @PutMapping("/dutyConfig")
+    @Operation(summary = "添加和修改值班配置", description = "修改添加值班配置")
+    public HttpResult<Object> getDutyConfig(@RequestBody WechatCustomerServiceDutyRulesVo sysWechatCustomerDutyRules) {
+        wechatCustomerServiceManageService.saveOrUpdateCustomerServiceDutyRules(sysWechatCustomerDutyRules);
+        return HttpResult.ok();
+    }
+
+    @PostMapping("/pageQuery")
+    @Operation(summary = "分页查询客服数据", description = "分页查询客服数据")
+    public HttpResult<Page<WechatCustomerServicePageVo>> pageQuery(@RequestBody WechatCustomerServiceQueryVo sysWechatCustomerQuery) {
+        Page<WechatCustomerServicePageVo> sysWechatCustomerVoBasePageResult = wechatCustomerServiceService.pageQuery(sysWechatCustomerQuery);
+        return HttpResult.ok(sysWechatCustomerVoBasePageResult);
+    }
+
+    @PostMapping
+    @Operation(summary = "添加客服", description = "添加客服")
+    public HttpResult<Object> add(@RequestBody @Valid WechatCustomerServiceVo sysWechatCustomerAddVo) throws WxErrorException {
+        wechatCustomerServiceManageService.addWechatCustomer(sysWechatCustomerAddVo);
+        return HttpResult.ok();
+    }
+
+    @GetMapping("/{customerServiceId}")
+    @Operation(summary = "编辑客服", description = "编辑客服")
+    public HttpResult<WechatCustomerServiceVo> get(@PathVariable Long customerServiceId) throws WxErrorException {
+        WechatCustomerServiceVo wechatCustomerAddVo = wechatCustomerServiceManageService.getWechatCustomer(customerServiceId);
+        return HttpResult.ok(wechatCustomerAddVo);
+    }
+
+    @PutMapping("/{customerServiceId}")
+    @Operation(summary = "修改客服", description = "修改客服")
+    public HttpResult<Object> revise(@PathVariable Long customerServiceId, @RequestBody WechatCustomerServiceVo sysWechatCustomerAddVo) throws WxErrorException {
+        wechatCustomerServiceManageService.updateWechatCustomer(customerServiceId, sysWechatCustomerAddVo);
+        return HttpResult.ok();
+    }
+
+    @DeleteMapping("/{customerServiceId}")
+    @Operation(summary = "删除客服", description = "删除客服")
+    public HttpResult<Object> delete(@PathVariable Long customerServiceId) throws WxErrorException {
+        wechatCustomerServiceManageService.deleteWechatCustomer(customerServiceId);
+        return HttpResult.ok();
+    }
+
+    @GetMapping(value = "/find/link")
+    @Operation(summary = "查询微信客服链接", description = "查询微信客服链接")
+    public HttpResult<String> findWechatCustomerLink() throws WxErrorException {
+        String url = wechatCustomerServiceManageService.getWeChatCustomer();
+        return HttpResult.ok(url);
+    }
+
+    @PostMapping(path = "/callback", consumes = MediaType.TEXT_XML_VALUE, produces = MediaType.TEXT_XML_VALUE)
+    @Operation(summary = "客服回调(处理事件发送欢迎语)", description = "客服回调(处理事件发送欢迎语)")
+    public HttpResult<String> customerCallback(@RequestBody WxCpXmlMessage wechatEncrypt) throws JsonProcessingException, WxErrorException {
+        wechatCustomerServiceManageService.callbackSendMsgOnEvent(wechatEncrypt);
+        return HttpResult.ok();
+    }
+
+}

+ 106 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/SysHolidays.java

@@ -0,0 +1,106 @@
+package com.jzg.organization.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+@TableName("sys_holidays")
+@Schema(name = "SysHolidays", description = "")
+public class SysHolidays implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @Schema(description = "id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 节日名称
+     */
+    @Schema(description = "节日名称")
+    private String holidayName;
+
+    /**
+     * 日期
+     */
+    @Schema(description = "日期")
+    private LocalDate date;
+
+    /**
+     * 是否是节假日
+     */
+    @Schema(description = "是否是节假日")
+    private Boolean isOffDay;
+
+    /**
+     * 是否是工作日
+     */
+    @Schema(description = "是否是工作日")
+    private Boolean isStatutory;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getHolidayName() {
+        return holidayName;
+    }
+
+    public void setHolidayName(String holidayName) {
+        this.holidayName = holidayName;
+    }
+
+    public LocalDate getDate() {
+        return date;
+    }
+
+    public void setDate(LocalDate date) {
+        this.date = date;
+    }
+
+    public Boolean getIsOffDay() {
+        return isOffDay;
+    }
+
+    public void setIsOffDay(Boolean isOffDay) {
+        this.isOffDay = isOffDay;
+    }
+
+    public Boolean getIsStatutory() {
+        return isStatutory;
+    }
+
+    public void setIsStatutory(Boolean isStatutory) {
+        this.isStatutory = isStatutory;
+    }
+
+    @Override
+    public String toString() {
+        return "SysHolidays{" +
+            "id = " + id +
+            ", holidayName = " + holidayName +
+            ", date = " + date +
+            ", isOffDay = " + isOffDay +
+            ", isStatutory = " + isStatutory +
+            "}";
+    }
+}

+ 87 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/WechatCustomerService.java

@@ -0,0 +1,87 @@
+package com.jzg.organization.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+@Data
+@TableName("wechat_customer_service")
+@Schema(name = "WechatCustomerService", description = "")
+public class WechatCustomerService implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+    /**
+     * id
+     */
+    @Schema(description = "id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+    /**
+     * 昵称
+     */
+    @Schema(description = "昵称")
+    private String nickname;
+    /**
+     * 头像
+     */
+    @Schema(description = "头像")
+    private String avatar;
+    /**
+     * 用户id
+     */
+    @Schema(description = "用户id")
+    private String userId;
+    /**
+     *
+     */
+    @Schema(description = "接待人企业微信客服")
+    private String receptionist;
+    /**
+     * 接待id
+     */
+    @Schema(description = "接待人企业微信用户id")
+    private String receptionistId;
+    /**
+     * 客服账号ID
+     */
+    @Schema(description = "客服账号ID")
+    private String openKfId;
+    /**
+     * 创建人
+     */
+    @Schema(description = "创建人")
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    @Schema(description = "创建时间")
+    private LocalDateTime createTime;
+    /**
+     * 更新人
+     */
+    @Schema(description = "更新人")
+    private String updateBy;
+    /**
+     * 更新时间
+     */
+    @Schema(description = "更新时间")
+    private LocalDateTime updateTime;
+
+}

+ 68 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/WechatCustomerServiceDuty.java

@@ -0,0 +1,68 @@
+package com.jzg.organization.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalTime;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+@Data
+@TableName("wechat_customer_service_duty")
+@Schema(name = "WechatCustomerServiceDuty", description = "")
+public class WechatCustomerServiceDuty implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @Schema(description = "id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 日期
+     */
+    @Schema(description = "日期")
+    private LocalDate date;
+
+    /**
+     * 开始时间
+     */
+    @Schema(description = "开始时间")
+    private LocalTime startTime;
+
+    /**
+     * 结束时间
+     */
+    @Schema(description = "结束时间")
+    private LocalTime endTime;
+
+    /**
+     * 值班客服id
+     */
+    @Schema(description = "值班客服id")
+    private Long customerServiceId;
+
+    /**
+     * 值班客服id
+     */
+    @Schema(description = "值班客服id")
+    private Long dutyCustomerServiceId;
+
+
+}

+ 91 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/WechatCustomerServiceRecording.java

@@ -0,0 +1,91 @@
+package com.jzg.organization.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 微信客服记录表
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-17
+ */
+@TableName("wechat_customer_service_recording")
+@Schema(name = "WechatCustomerServiceRecording", description = "微信客服记录表")
+public class WechatCustomerServiceRecording implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @Schema(description = "id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 客服id
+     */
+    @Schema(description = "客服id")
+    private Long customerServiceId;
+
+    /**
+     * 用户id
+     */
+    @Schema(description = "用户id")
+    private String userId;
+
+    /**
+     * 创建时间
+     */
+    @Schema(description = "创建时间")
+    private LocalDateTime createTime;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getCustomerServiceId() {
+        return customerServiceId;
+    }
+
+    public void setCustomerServiceId(Long customerServiceId) {
+        this.customerServiceId = customerServiceId;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public LocalDateTime getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(LocalDateTime createTime) {
+        this.createTime = createTime;
+    }
+
+    @Override
+    public String toString() {
+        return "WechatCustomerServiceRecording{" +
+            "id = " + id +
+            ", customerServiceId = " + customerServiceId +
+            ", userId = " + userId +
+            ", createTime = " + createTime +
+            "}";
+    }
+}

+ 46 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/dto/WechatCustomerServicePageDto.java

@@ -0,0 +1,46 @@
+package com.jzg.organization.entity.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+@Data
+public class WechatCustomerServicePageDto implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = -4249646362921820406L;
+
+    @Schema(description = "id")
+    private Long id;
+
+    @Schema(description = "文件名称")
+    private String fileName;
+
+    @Schema(description = "桶名称")
+    private String bucketName;
+
+    @Schema(description = "昵称")
+    private String nickname;
+
+    @Schema(description = "接待人员")
+    private String receptionist;
+
+    @Schema(description = "用户名称")
+    private String userName;
+
+    @Schema(description = "用户id")
+    private String userId;
+
+    @Schema(description = "添加时间")
+    private String createTime;
+
+    @Schema(description = "是否排班")
+    private boolean isScheduling;
+
+}
+
+
+
+

+ 36 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/vo/WeComDeptVo.java

@@ -0,0 +1,36 @@
+package com.jzg.organization.entity.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import me.chanjar.weixin.cp.bean.WxCpDepart;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@Schema(description = "微信部门信息")
+public class WeComDeptVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 5154076136571383722L;
+
+    @Schema(description ="部门编号")
+    private String deptId;
+
+    @Schema(description ="部门名称")
+    private String deptName;
+
+    @Schema(description ="上级部门编号")
+    private String parentId;
+
+    @Schema(description ="下级部门列表")
+    private List<WeComDeptVo> childDept;
+
+    public WeComDeptVo(WxCpDepart wxCpDepart) {
+        this.deptId = String.valueOf(wxCpDepart.getId());
+        this.deptName = wxCpDepart.getName();
+        this.parentId = String.valueOf(wxCpDepart.getParentId());
+    }
+
+}

+ 19 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/vo/WeComUserVo.java

@@ -0,0 +1,19 @@
+package com.jzg.organization.entity.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+
+@Data
+@Schema(description = "企业微信用户")
+@AllArgsConstructor
+public class WeComUserVo {
+
+    @Schema(description = "成员UserID")
+    private String userId;
+
+    @Schema(description = "名称")
+    private String name;
+
+}

+ 24 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/vo/WechatCustomerServiceDutyRulesVo.java

@@ -0,0 +1,24 @@
+package com.jzg.organization.entity.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @ClassName WechatCusto merServiceDutyRulesVo
+ * @Description 客服排班规则
+ * @Author wenks
+ * @Date 2025/9/16 17:46
+ * @Version 1.0
+ */
+@Data
+public class WechatCustomerServiceDutyRulesVo {
+
+    @Schema(description = "客服id")
+    private Long customerId;
+
+    @Schema(description = "排班列表")
+    private List<WechatCustomerServiceDutyVo> dutyList;
+
+}

+ 46 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/vo/WechatCustomerServiceDutyVo.java

@@ -0,0 +1,46 @@
+package com.jzg.organization.entity.vo;
+
+import com.jzg.organization.entity.WechatCustomerServiceDuty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.util.List;
+
+@Data
+public class WechatCustomerServiceDutyVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = -1235995261003143896L;
+
+    @Schema(description = "排班日期")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate dutyDate;
+
+    @Schema(description = "排班配置")
+    private List<DutyConfigVo> dutyConfig;
+
+    @Data
+    public static class DutyConfigVo implements Serializable {
+
+        @Serial
+        private static final long serialVersionUID = 4718022850400485048L;
+
+        @Schema(description = "开始时间")
+        @DateTimeFormat(pattern = "HH:mm:ss")
+        private LocalTime startTime;
+
+        @Schema(description = "结束时间")
+        @DateTimeFormat(pattern = "HH:mm:ss")
+        private LocalTime endTime;
+
+        @Schema(description = "客服id")
+        private Long dutyCustomerServiceId;
+
+    }
+
+}

+ 56 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/vo/WechatCustomerServicePageVo.java

@@ -0,0 +1,56 @@
+package com.jzg.organization.entity.vo;
+
+import com.jzg.organization.entity.dto.WechatCustomerServicePageDto;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @ClassName WechatCustomerServicePageVo
+ * @Description
+ * @Author wenks
+ * @Date 2025/9/16 16:41
+ * @Version 1.0
+ */
+@Data
+public class WechatCustomerServicePageVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = -8011588804872634501L;
+
+    @Schema(description = "id")
+    private Long id;
+
+    @Schema(description = "昵称" )
+    private String nickname;
+
+    @Schema(description = "昵称")
+    private String avatar;
+
+    @Schema(description = "接待人员")
+    private String receptionist;
+
+    @Schema(description = "用户名称")
+    private String userName;
+
+    @Schema(description = "用户id")
+    private String userId;
+
+    @Schema(description = "添加时间")
+    private String createTime;
+
+    @Schema(description = "是否排班")
+    private boolean isScheduling;
+
+    public WechatCustomerServicePageVo(WechatCustomerServicePageDto servicePageDto) {
+        this.id = servicePageDto.getId();
+        this.nickname = servicePageDto.getNickname();
+        this.receptionist = servicePageDto.getReceptionist();
+        this.userName = servicePageDto.getUserName();
+        this.userId = servicePageDto.getUserId();
+        this.createTime = servicePageDto.getCreateTime();
+        this.isScheduling = servicePageDto.isScheduling();
+    }
+}

+ 25 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/vo/WechatCustomerServiceQueryVo.java

@@ -0,0 +1,25 @@
+package com.jzg.organization.entity.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+@Data
+public class WechatCustomerServiceQueryVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = -6579335855162941716L;
+
+    @Schema(description = "昵称" )
+    private String nickname;
+
+    @Schema(description = "页码" )
+    private Integer pageNum = 1;
+
+    @Schema(description = "每页数据量" )
+    private Integer pageSize = 10;
+
+}

+ 69 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/vo/WechatCustomerServiceVo.java

@@ -0,0 +1,69 @@
+package com.jzg.organization.entity.vo;
+
+import com.jzg.organization.entity.WechatCustomerService;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+
+/**
+ * @ClassName WechatCustomerServiceVo
+ * @Description 企业微信上传接口
+ * @Author wenks
+ * @Date 2025/9/16 14:39
+ * @Version 1.0
+ */
+@Data
+@NoArgsConstructor
+public class WechatCustomerServiceVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 3803863574919502778L;
+
+    @Schema(description = "昵称")
+    @NotBlank(message = "请输入客服昵称")
+    private String nickname;
+
+    @Schema(description = "客服头像")
+    @NotBlank(message = "客服头像必须传入")
+    private String avatar;
+
+    @Schema(description = "后线人员")
+    @NotBlank(message = "请输入后线人员")
+    private String userId;
+
+    @Schema(description = "接待人企业微信客服")
+    @NotBlank(message = "请输入企业微信用户")
+    private String receptionist;
+
+    @Schema(description = "接待人企业微信用户id")
+    @NotBlank(message = "请输入企业微信用户")
+    private String receptionistId;
+
+    public WechatCustomerService buildWechatCustomerService(String userName){
+        WechatCustomerService wechatCustomerService = new WechatCustomerService();
+        wechatCustomerService.setNickname(this.nickname);
+        wechatCustomerService.setUserId(this.userId);
+        wechatCustomerService.setReceptionist(this.receptionist);
+        wechatCustomerService.setReceptionistId(this.receptionistId);
+        wechatCustomerService.setCreateTime(LocalDateTime.now());
+        wechatCustomerService.setCreateBy(userName);
+        wechatCustomerService.setUpdateTime(LocalDateTime.now());
+        wechatCustomerService.setUpdateBy(userName);
+        return wechatCustomerService;
+    }
+
+    public WechatCustomerServiceVo(WechatCustomerService wechatCustomerService) {
+        this.nickname = wechatCustomerService.getNickname();
+        this.avatar = wechatCustomerService.getAvatar();
+        this.userId = wechatCustomerService.getUserId();
+        this.receptionist = wechatCustomerService.getReceptionist();
+        this.receptionistId = wechatCustomerService.getReceptionistId();
+    }
+
+}

+ 16 - 0
tenant/organization/src/main/java/com/jzg/organization/mapper/SysHolidaysMapper.java

@@ -0,0 +1,16 @@
+package com.jzg.organization.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jzg.organization.entity.SysHolidays;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+public interface SysHolidaysMapper extends BaseMapper<SysHolidays> {
+
+}

+ 16 - 0
tenant/organization/src/main/java/com/jzg/organization/mapper/WechatCustomerServiceDutyMapper.java

@@ -0,0 +1,16 @@
+package com.jzg.organization.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jzg.organization.entity.WechatCustomerServiceDuty;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+public interface WechatCustomerServiceDutyMapper extends BaseMapper<WechatCustomerServiceDuty> {
+
+}

+ 28 - 0
tenant/organization/src/main/java/com/jzg/organization/mapper/WechatCustomerServiceMapper.java

@@ -0,0 +1,28 @@
+package com.jzg.organization.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jzg.organization.entity.WechatCustomerService;
+import com.jzg.organization.entity.dto.WechatCustomerServicePageDto;
+import com.jzg.organization.entity.vo.WechatCustomerServicePageVo;
+import com.jzg.organization.entity.vo.WechatCustomerServiceQueryVo;
+import org.springframework.data.repository.query.Param;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+public interface WechatCustomerServiceMapper extends BaseMapper<WechatCustomerService> {
+
+    /**
+     * 分页查询
+     * @param page 分页查询
+     * @param sysWechatCustomerQuery 查询参数
+     * @return
+     */
+    Page<WechatCustomerServicePageDto> pageQuery(Page<WechatCustomerServicePageDto> page, @Param("sysWechatCustomerQuery") WechatCustomerServiceQueryVo sysWechatCustomerQuery);
+}

+ 16 - 0
tenant/organization/src/main/java/com/jzg/organization/mapper/WechatCustomerServiceRecordingMapper.java

@@ -0,0 +1,16 @@
+package com.jzg.organization.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jzg.organization.entity.WechatCustomerServiceRecording;
+
+/**
+ * <p>
+ * 微信客服记录表 Mapper 接口
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-17
+ */
+public interface WechatCustomerServiceRecordingMapper extends BaseMapper<WechatCustomerServiceRecording> {
+
+}

+ 16 - 0
tenant/organization/src/main/java/com/jzg/organization/service/ISysHolidaysService.java

@@ -0,0 +1,16 @@
+package com.jzg.organization.service;
+
+import com.jzg.organization.entity.SysHolidays;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+public interface ISysHolidaysService extends IService<SysHolidays> {
+
+}

+ 37 - 0
tenant/organization/src/main/java/com/jzg/organization/service/IWechatCustomerServiceDutyService.java

@@ -0,0 +1,37 @@
+package com.jzg.organization.service;
+
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.jzg.organization.entity.WechatCustomerServiceDuty;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.jzg.organization.entity.vo.WechatCustomerServiceDutyRulesVo;
+import com.jzg.organization.entity.vo.WechatCustomerServiceDutyVo;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 服务类
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+public interface IWechatCustomerServiceDutyService extends IService<WechatCustomerServiceDuty> {
+
+    /**
+     * 清空客服的接待
+     *
+     * @param customerServiceId 客服id
+     */
+    void clearCustomerDuty(Long customerServiceId);
+
+
+    /**
+     * 获取客服的接待
+     *
+     * @param customerId 客服id
+     * @return 客服的接待
+     */
+    List<WechatCustomerServiceDutyVo> getCustomerServiceDutyRules(String customerId);
+
+}

+ 16 - 0
tenant/organization/src/main/java/com/jzg/organization/service/IWechatCustomerServiceRecordingService.java

@@ -0,0 +1,16 @@
+package com.jzg.organization.service;
+
+import com.jzg.organization.entity.WechatCustomerServiceRecording;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 微信客服记录表 服务类
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-17
+ */
+public interface IWechatCustomerServiceRecordingService extends IService<WechatCustomerServiceRecording> {
+
+}

+ 94 - 0
tenant/organization/src/main/java/com/jzg/organization/service/IWechatCustomerServiceService.java

@@ -0,0 +1,94 @@
+package com.jzg.organization.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jzg.commons.exception.SystemException;
+import com.jzg.organization.entity.WechatCustomerService;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.jzg.organization.entity.vo.WechatCustomerServicePageVo;
+import com.jzg.organization.entity.vo.WechatCustomerServiceQueryVo;
+import com.jzg.organization.entity.vo.WechatCustomerServiceVo;
+
+import javax.validation.constraints.NotBlank;
+import java.util.List;
+
+/**
+ * <p>
+ * 服务类
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+public interface IWechatCustomerServiceService extends IService<WechatCustomerService> {
+    /**
+     * 删除所有信息
+     *
+     * @param customerServiceId 客服id
+     */
+    void deleteAllInfo(Long customerServiceId);
+
+    /**
+     * 客服昵称是否重复
+     *
+     * @param nickname 客服昵称
+     */
+    default void isNicknameRepeat(@NotBlank(message = "请输入客服昵称") String nickname) {
+        List<WechatCustomerService> list = lambdaQuery().eq(WechatCustomerService::getNickname, nickname).list();
+        if (!list.isEmpty()) {
+            throw new SystemException("客服昵称已存在");
+        }
+    }
+
+    /**
+     * 客服员工账号是否重复
+     *
+     * @param userId 用户id
+     */
+    default void isUserIdRepeat(@NotBlank(message = "请输入后线人员") String userId) {
+        List<WechatCustomerService> list = lambdaQuery().eq(WechatCustomerService::getUserId, userId).list();
+        if (!list.isEmpty()) {
+            throw new SystemException("关联的员工账号已存在");
+        }
+    }
+
+    /**
+     * 获取客服信息
+     *
+     * @param customerServiceId 客服id
+     * @param message           错误信息
+     * @return
+     */
+    default WechatCustomerService getByIdExist(Long customerServiceId, String message) {
+        WechatCustomerService wechatCustomerService = getById(customerServiceId);
+        if (wechatCustomerService == null) {
+            throw new SystemException(message);
+        }
+        return wechatCustomerService;
+    }
+
+    /**
+     * 分页查询
+     *
+     * @param sysWechatCustomerQuery 查询参数
+     * @return
+     */
+    Page<WechatCustomerServicePageVo> pageQuery(WechatCustomerServiceQueryVo sysWechatCustomerQuery);
+
+    /**
+     * 根据员工账号获取客服信息
+     *
+     * @param userId 员工账号
+     * @return
+     */
+    default WechatCustomerService getByUserId(String userId){
+        return lambdaQuery().eq(WechatCustomerService::getUserId, userId).one();
+    }
+
+    /**
+     * 获取客服id
+     *
+     * @param wechatCustomerService 客服信息
+     * @return
+     */
+    WechatCustomerService getCacheCustomerId(WechatCustomerService wechatCustomerService);
+}

+ 26 - 0
tenant/organization/src/main/java/com/jzg/organization/service/SysUserService.java

@@ -8,9 +8,11 @@ import com.jzg.commons.entity.dto.SysUserJzgInfoDto;
 import com.jzg.commons.entity.po.SysUser;
 import com.jzg.commons.entity.user.vo.SysTennatVo;
 import com.jzg.commons.entity.vo.*;
+import com.jzg.commons.exception.SystemException;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 
+import javax.validation.constraints.NotBlank;
 import java.util.List;
 
 /**
@@ -167,4 +169,28 @@ public interface SysUserService extends IService<SysUser> {
      * @param userId     用户id
      */
     void setTenantList(String systemCode, String userId);
+
+    /**
+     * 判断用户是否在职
+     *
+     * @param userId 用户id
+     * @return
+     */
+    default void isOnTheJob(@NotBlank(message = "请输入后线人员") String userId) {
+        SysUser sysUser = this.getById(userId);
+        if (sysUser == null) {
+            throw new SystemException("用户不存在");
+        }
+        if (1 != sysUser.getAccountStatus()) {
+            throw new SystemException("关联员工状态账号异常,刷新后重试");
+        }
+    }
+
+    /**
+     * 获取上级id
+     *
+     * @param username 用户id
+     * @return 上级id
+     */
+    String getLeaderId(String username);
 }

+ 84 - 0
tenant/organization/src/main/java/com/jzg/organization/service/WechatCustomerServiceManageService.java

@@ -0,0 +1,84 @@
+package com.jzg.organization.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jzg.organization.entity.vo.*;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
+
+import javax.validation.constraints.NotBlank;
+import java.util.List;
+
+/**
+ * @ClassName WechatCustomerServiceManageService
+ * @Description 客服管理服务
+ * @Author wenks
+ * @Date 2025/9/16 11:38
+ * @Version 1.0
+ */
+public interface WechatCustomerServiceManageService {
+
+    /**
+     * 添加客服
+     *
+     * @param sysWechatCustomerAddVo 客服信息
+     */
+    void addWechatCustomer(WechatCustomerServiceVo sysWechatCustomerAddVo) throws WxErrorException;
+
+    /**
+     * 获取客服信息
+     *
+     * @param customerServiceId 客服id
+     * @return 客服信息
+     */
+    WechatCustomerServiceVo getWechatCustomer(Long customerServiceId);
+
+    /**
+     * 删除客服
+     *
+     * @param customerServiceId 客服id
+     */
+    void deleteWechatCustomer(Long customerServiceId) throws WxErrorException;
+
+    /**
+     * 修改客服
+     *
+     * @param customerServiceId      客服id
+     * @param sysWechatCustomerAddVo 客服信息
+     */
+    void updateWechatCustomer(Long customerServiceId, WechatCustomerServiceVo sysWechatCustomerAddVo) throws WxErrorException;
+
+    /**
+     * 获取部门树
+     *
+     * @return 部门树
+     */
+    List<WeComDeptVo> getDeptByDeptId() throws WxErrorException;
+
+    /**
+     * 获取部门下的用户列表
+     *
+     * @return 用户列表
+     */
+    List<WeComUserVo> getUser() throws WxErrorException;
+
+    /**
+     * 保存或者更新客服的接待
+     *
+     * @param sysWechatCustomerDutyRules 客服的接待
+     */
+    void saveOrUpdateCustomerServiceDutyRules(WechatCustomerServiceDutyRulesVo sysWechatCustomerDutyRules);
+
+    /**
+     * 通过领导人的userId获取跳转链接
+     *
+     * @return 跳转链接
+     */
+    String getWeChatCustomer() throws WxErrorException;
+
+    /**
+     * 客服事件回调
+     *
+     * @param wechatEncrypt 微信加密字符串
+     */
+    void callbackSendMsgOnEvent(WxCpXmlMessage wechatEncrypt);
+}

+ 20 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/SysHolidaysServiceImpl.java

@@ -0,0 +1,20 @@
+package com.jzg.organization.service.impl;
+
+import com.jzg.organization.entity.SysHolidays;
+import com.jzg.organization.mapper.SysHolidaysMapper;
+import com.jzg.organization.service.ISysHolidaysService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+@Service
+public class SysHolidaysServiceImpl extends ServiceImpl<SysHolidaysMapper, SysHolidays> implements ISysHolidaysService {
+
+}

+ 10 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserServiceImpl.java

@@ -37,6 +37,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.ObjectUtils;
 
 import java.util.*;
 import java.util.stream.Collectors;
@@ -847,6 +848,15 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
        redissonClient.getBucket(RedisKeyConstants.APP_SYSTEM_CODE + userId).set(systemCode);
     }
 
+    @Override
+    public String getLeaderId(String username) {
+        SysUser sysUser = lambdaQuery().eq(SysUser::getUsername, username).one();
+        if (ObjectUtils.isEmpty(sysUser)) {
+            throw new SystemException("用户不存在");
+        }
+        SysUserJzgInfo sysUserJzgInfo = sysUserJzgInfoService.getUserById(sysUser.getId());
+        return sysUserJzgInfo.getLeaderId();
+    }
 }
 
 

+ 80 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/WechatCustomerServiceDutyServiceImpl.java

@@ -0,0 +1,80 @@
+package com.jzg.organization.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.jzg.organization.entity.WechatCustomerServiceDuty;
+import com.jzg.organization.entity.vo.WechatCustomerServiceDutyRulesVo;
+import com.jzg.organization.entity.vo.WechatCustomerServiceDutyVo;
+import com.jzg.organization.mapper.WechatCustomerServiceDutyMapper;
+import com.jzg.organization.service.IWechatCustomerServiceDutyService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 服务实现类
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+@Service
+public class WechatCustomerServiceDutyServiceImpl extends ServiceImpl<WechatCustomerServiceDutyMapper, WechatCustomerServiceDuty> implements IWechatCustomerServiceDutyService {
+
+    @Override
+    public void clearCustomerDuty(Long customerServiceId) {
+        LambdaUpdateWrapper<WechatCustomerServiceDuty> wrapper = new LambdaUpdateWrapper<WechatCustomerServiceDuty>().eq(WechatCustomerServiceDuty::getCustomerServiceId, customerServiceId);
+        remove(wrapper);
+    }
+
+    @Override
+    public List<WechatCustomerServiceDutyVo> getCustomerServiceDutyRules(String customerId) {
+        // 使用分组收集器直接构建分组Map
+        Map<LocalDate, List<WechatCustomerServiceDuty>> dutyMap = lambdaQuery()
+                .eq(WechatCustomerServiceDuty::getCustomerServiceId, customerId)
+                .list()
+                .stream()
+                .collect(Collectors.groupingBy(WechatCustomerServiceDuty::getDate));
+
+
+        return dutyMap.entrySet().stream()
+                .map(entry -> {
+                    WechatCustomerServiceDutyVo vo = new WechatCustomerServiceDutyVo();
+                    // 格式化日期为 yyyy-MM-dd
+                    vo.setDutyDate(entry.getKey());
+
+                    // 转换并格式化时间
+                    List<WechatCustomerServiceDutyVo.DutyConfigVo> configs = entry.getValue().stream()
+                            .map(this::convertToDutyConfigVo)
+                            .toList();
+
+                    vo.setDutyConfig(configs);
+                    return vo;
+                })
+                .toList();
+    }
+
+    // 使用格式化器转换时间
+    private WechatCustomerServiceDutyVo.DutyConfigVo convertToDutyConfigVo(
+            WechatCustomerServiceDuty duty) {
+
+        WechatCustomerServiceDutyVo.DutyConfigVo configVo = new WechatCustomerServiceDutyVo.DutyConfigVo();
+
+        // 格式化开始和结束时间
+        configVo.setStartTime(duty.getStartTime());
+        configVo.setEndTime(duty.getEndTime());
+
+        configVo.setDutyCustomerServiceId(duty.getDutyCustomerServiceId());
+        return configVo;
+    }
+
+
+}

+ 303 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/WechatCustomerServiceManageServiceImpl.java

@@ -0,0 +1,303 @@
+package com.jzg.organization.service.impl;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jzg.commons.core.base.BaseController;
+import com.jzg.commons.entity.po.SysUploadFiles;
+import com.jzg.commons.entity.vo.SysUserAccountVo;
+import com.jzg.commons.exception.SystemException;
+import com.jzg.commons.util.MinioUtils;
+import com.jzg.organization.entity.WechatCustomerService;
+import com.jzg.organization.entity.WechatCustomerServiceDuty;
+import com.jzg.organization.entity.WechatCustomerServiceRecording;
+import com.jzg.organization.entity.vo.*;
+import com.jzg.organization.mapper.SysUploadFilesMapper;
+import com.jzg.organization.service.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.crypto.WxCryptUtil;
+import me.chanjar.weixin.cp.api.*;
+import me.chanjar.weixin.cp.bean.WxCpBaseResp;
+import me.chanjar.weixin.cp.bean.WxCpDepart;
+import me.chanjar.weixin.cp.bean.WxCpUser;
+import me.chanjar.weixin.cp.bean.kf.*;
+import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
+import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
+import me.chanjar.weixin.cp.message.WxCpMessageRouter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+
+import java.io.File;
+import java.io.InputStream;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class WechatCustomerServiceManageServiceImpl implements WechatCustomerServiceManageService {
+
+    private final IWechatCustomerServiceService wechatCustomerServiceService;
+
+    private final IWechatCustomerServiceDutyService wechatCustomerServiceDutyService;
+
+    private final IWechatCustomerServiceRecordingService wechatCustomerServiceRecordingService;
+
+    private final MinioUtils minioUtils;
+
+    private final SysUserService sysUserService;
+
+    private final WxCpService wxCpService;
+
+    private final WxCpMessageRouter wxCpMessageRouter;
+
+    private final WxCpMediaService wxCpMediaService;
+
+    private final WxCpKfService wxCpKfService;
+
+    private final WxCpUserService wxCpUserService;
+
+    private final WxCpDepartmentService wxCpDepartmentService;
+
+    private final SysUploadFilesMapper sysUploadFilesMapper;
+
+    private final BaseController baseController;
+
+    @Value("${minio.bucket-name}")
+    private String bucketName;
+
+    @Override
+    public WechatCustomerServiceVo getWechatCustomer(Long customerServiceId) {
+        WechatCustomerService wechatCustomerService = wechatCustomerServiceService.getById(customerServiceId);
+        return Optional.ofNullable(wechatCustomerService).map(WechatCustomerServiceVo::new).orElse(new WechatCustomerServiceVo());
+    }
+
+    @Override
+    public void addWechatCustomer(WechatCustomerServiceVo sysWechatCustomerAddVo) throws WxErrorException {
+        String userName = baseController.getUserName();
+        // 判断昵称是否重复
+        wechatCustomerServiceService.isNicknameRepeat(sysWechatCustomerAddVo.getNickname());
+        // 判断员工账号是否在职
+        sysUserService.isOnTheJob(sysWechatCustomerAddVo.getUserId());
+        // 判断员工账号是否与其他客服账号关联
+        wechatCustomerServiceService.isUserIdRepeat(sysWechatCustomerAddVo.getUserId());
+
+        WxCpKfAccountAdd wxCpKfAccountAdd = new WxCpKfAccountAdd();
+        wxCpKfAccountAdd.setName(sysWechatCustomerAddVo.getNickname());
+        // 头像
+        WechatCustomerService wechatCustomerService = sysWechatCustomerAddVo.buildWechatCustomerService(userName);
+
+        if (StringUtils.hasLength(sysWechatCustomerAddVo.getAvatar())) {
+            SysUploadFiles sysUploadFiles = sysUploadFilesMapper.selectById(sysWechatCustomerAddVo.getAvatar());
+            Optional.ofNullable(sysUploadFiles).map(SysUploadFiles::getFileName).ifPresent(fileName -> {
+                InputStream inputStream = minioUtils.getObject(bucketName, fileName);
+                // 上传素材
+                WxMediaUploadResult image;
+                try {
+                    image = wxCpMediaService.upload("image", inputStream, fileName);
+                } catch (WxErrorException e) {
+                    throw new SystemException("图片上传失败");
+                }
+                String mediaId = image.getMediaId();
+                wxCpKfAccountAdd.setMediaId(mediaId);
+                wechatCustomerService.setAvatar(sysUploadFiles.getId());
+            });
+        }
+        // 添加
+        WxCpKfAccountAddResp wxCpKfAccountAddResp = wxCpKfService.addAccount(wxCpKfAccountAdd);
+        wechatCustomerService.setOpenKfId(wxCpKfAccountAddResp.getOpenKfid());
+        List<String> list = new ArrayList<>();
+        list.add(sysWechatCustomerAddVo.getReceptionistId());
+        WxCpKfServicerOpResp wxCpKfServicerOpResp = wxCpKfService.addServicer(wxCpKfAccountAddResp.getOpenKfid(), list);
+        if (wxCpKfServicerOpResp.getErrcode() == 0) {
+            wechatCustomerServiceService.save(wechatCustomerService);
+        }
+
+    }
+
+    @Override
+    public void deleteWechatCustomer(Long customerServiceId) throws WxErrorException {
+        WechatCustomerService wechatCustomerService = wechatCustomerServiceService.getByIdExist(customerServiceId, "客服不存在");
+        WxCpKfAccountDel wxCpKfAccountDel = new WxCpKfAccountDel();
+        wxCpKfAccountDel.setOpenKfid(wechatCustomerService.getOpenKfId());
+        WxCpBaseResp wxCpBaseResp;
+        wxCpBaseResp = wxCpKfService.delAccount(wxCpKfAccountDel);
+        if (wxCpBaseResp.getErrcode() == 0) {
+            wechatCustomerServiceService.deleteAllInfo(customerServiceId);
+        }
+    }
+
+    @Override
+    public void updateWechatCustomer(Long customerServiceId, WechatCustomerServiceVo wechatCustomerServiceVo) throws WxErrorException {
+        WechatCustomerService wechatCustomerService = wechatCustomerServiceService.getByIdExist(customerServiceId, "客服不存在");
+        if (!wechatCustomerService.getNickname().equals(wechatCustomerServiceVo.getNickname())) {
+            wechatCustomerServiceService.isNicknameRepeat(wechatCustomerServiceVo.getNickname());
+        }
+
+        WxCpKfAccountUpd wxCpKfAccountUpd = new WxCpKfAccountUpd();
+        wxCpKfAccountUpd.setOpenKfid(wechatCustomerService.getOpenKfId());
+        boolean isAvatarSame = StringUtils.hasLength(wechatCustomerServiceVo.getAvatar()) && !wechatCustomerServiceVo.getAvatar().equals(wechatCustomerService.getAvatar());
+
+        // 头像是否更换
+        if (isAvatarSame) {
+            SysUploadFiles sysUploadFiles = sysUploadFilesMapper.selectById(wechatCustomerServiceVo.getAvatar());
+            InputStream inputStream = minioUtils.getObject(bucketName, sysUploadFiles.getFileName());
+            WxMediaUploadResult image = wxCpMediaService.upload("image", inputStream, sysUploadFiles.getFileName());
+            String mediaId = image.getMediaId();
+            wxCpKfAccountUpd.setMediaId(mediaId);
+            wechatCustomerService.setAvatar(wechatCustomerServiceVo.getAvatar());
+        }
+
+        // 昵称是否相同
+        boolean isNicknameSame = !wechatCustomerService.getNickname().equals(wechatCustomerServiceVo.getNickname());
+        if (isNicknameSame) {
+            wxCpKfAccountUpd.setName(wechatCustomerServiceVo.getNickname());
+        }
+
+        // 客服人员是否替换
+        if (!wechatCustomerService.getReceptionistId().equals(wechatCustomerServiceVo.getReceptionistId())) {
+            List<String> list = new ArrayList<>();
+            list.add(wechatCustomerService.getReceptionistId());
+            wxCpKfService.delServicer(wechatCustomerService.getOpenKfId(), list);
+            list = new ArrayList<>();
+            list.add(wechatCustomerServiceVo.getReceptionistId());
+            wxCpKfService.addServicer(wechatCustomerService.getOpenKfId(), list);
+            wechatCustomerService.setReceptionistId(wechatCustomerServiceVo.getReceptionistId());
+            wechatCustomerService.setReceptionist(wechatCustomerServiceVo.getReceptionist());
+        }
+
+        // 昵称和头像是否跟换
+        if (isNicknameSame || isAvatarSame) {
+            wxCpKfService.updAccount(wxCpKfAccountUpd);
+        }
+
+        wechatCustomerService.setNickname(wechatCustomerServiceVo.getNickname());
+        wechatCustomerService.setAvatar(wechatCustomerServiceVo.getAvatar());
+        wechatCustomerService.setUserId(wechatCustomerServiceVo.getUserId());
+        String userName = baseController.getUserName();
+        wechatCustomerService.setUpdateBy(userName);
+        wechatCustomerService.setUpdateTime(LocalDateTime.now());
+        wechatCustomerServiceService.updateById(wechatCustomerService);
+    }
+
+    @Override
+    public List<WeComDeptVo> getDeptByDeptId() throws WxErrorException {
+        List<WxCpDepart> list = wxCpDepartmentService.list(null);
+        List<WeComDeptVo> deptVos = list.stream()
+                .map(WeComDeptVo::new)
+                .toList();
+        Map<String, List<WeComDeptVo>> parentGroup = deptVos.stream()
+                .collect(Collectors.groupingBy(WeComDeptVo::getParentId));
+        List<String> collect = deptVos.stream().map(WeComDeptVo::getDeptId).toList();
+        deptVos.forEach(node -> node.setChildDept(parentGroup.getOrDefault(node.getDeptId(), Collections.emptyList())));
+        return deptVos.stream()
+                .filter(node -> node.getParentId() != null && !collect.contains(node.getParentId()))
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<WeComUserVo> getUser() throws WxErrorException {
+        List<WxCpUser> wxCpUsers = wxCpUserService.listSimpleByDepartment(9L, true, 0);
+        return wxCpUsers.stream().map(x -> new WeComUserVo(x.getUserId(), x.getName())).collect(Collectors.toList());
+    }
+
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void saveOrUpdateCustomerServiceDutyRules(WechatCustomerServiceDutyRulesVo sysWechatCustomerDutyRules) {
+        // 删除之前的排班信息
+        wechatCustomerServiceDutyService.clearCustomerDuty(sysWechatCustomerDutyRules.getCustomerId());
+        List<WechatCustomerServiceDuty> wechatCustomerServiceDuties = sysWechatCustomerDutyRules.getDutyList()
+                .stream()
+                .flatMap(duty -> duty.getDutyConfig().stream()
+                        .map(config -> {
+                            WechatCustomerServiceDuty dutyEntity = new WechatCustomerServiceDuty();
+                            dutyEntity.setCustomerServiceId(sysWechatCustomerDutyRules.getCustomerId());
+                            dutyEntity.setDutyCustomerServiceId(config.getDutyCustomerServiceId());
+                            dutyEntity.setDate(duty.getDutyDate());
+                            dutyEntity.setStartTime(config.getStartTime());
+                            dutyEntity.setEndTime(config.getEndTime());
+                            return dutyEntity;
+                        }))
+                .collect(Collectors.toList());
+        // 保存排班信息
+        wechatCustomerServiceDutyService.saveBatch(wechatCustomerServiceDuties);
+    }
+
+    @Override
+    public String getWeChatCustomer() throws WxErrorException {
+//        String userName = baseController.getUserName();
+        WechatCustomerService wechatCustomerService = null;
+//        String leaderId = sysUserService.getLeaderId(userName);
+        String userName = "1930514052662677506";
+        String leaderId = "1930514052662677506";
+        if (StringUtils.hasLength(leaderId)) {
+            wechatCustomerService = wechatCustomerServiceService.getByUserId(leaderId);
+        }
+
+        if (ObjectUtils.isEmpty(wechatCustomerService)) {
+            // 获取最近一次的客服记录
+            List<WechatCustomerService> sysWechatCustomerList = wechatCustomerServiceService.list();
+            List<Long> sysWechatCustomerIdList = sysWechatCustomerList.stream()
+                    .map(WechatCustomerService::getId)
+                    .collect(Collectors.toList());
+
+            WechatCustomerServiceRecording wechatCustomerServiceRecording = wechatCustomerServiceRecordingService.lambdaQuery()
+                    .in(!sysWechatCustomerIdList.isEmpty(), WechatCustomerServiceRecording::getCustomerServiceId, sysWechatCustomerIdList)
+                    .eq(WechatCustomerServiceRecording::getUserId, userName)
+                    .orderByDesc(WechatCustomerServiceRecording::getCreateTime)
+                    .last("limit 1")
+                    .one();
+            if (ObjectUtils.isEmpty(wechatCustomerServiceRecording)) {
+                wechatCustomerService = wechatCustomerServiceService.getCacheCustomerId(wechatCustomerService);
+            } else {
+                // 使用上一次的客服
+                wechatCustomerService = wechatCustomerServiceService.lambdaQuery()
+                        .eq(WechatCustomerService::getId, wechatCustomerServiceRecording.getCustomerServiceId())
+                        .one();
+                if (ObjectUtils.isEmpty(wechatCustomerService)) {
+                    wechatCustomerService = wechatCustomerServiceService.getCacheCustomerId(wechatCustomerService);
+                }
+            }
+            WechatCustomerServiceRecording customerRecording = new WechatCustomerServiceRecording();
+            customerRecording.setCustomerServiceId(wechatCustomerService.getId());
+            customerRecording.setUserId(userName);
+            wechatCustomerServiceRecordingService.save(customerRecording);
+        }
+
+        List<WechatCustomerServiceDuty> list = wechatCustomerServiceDutyService.lambdaQuery()
+                .eq(WechatCustomerServiceDuty::getDutyCustomerServiceId, wechatCustomerService.getId())
+                .eq(WechatCustomerServiceDuty::getDate, LocalDate.now())
+                .le(WechatCustomerServiceDuty::getStartTime, LocalTime.now())
+                .ge(WechatCustomerServiceDuty::getEndTime, LocalTime.now())
+                .list();
+        if (list != null && !list.isEmpty()) {
+            WechatCustomerServiceDuty wechatCustomerServiceDuty = list.get(0);
+            wechatCustomerService = wechatCustomerServiceService.getById(wechatCustomerServiceDuty.getDutyCustomerServiceId());
+        }
+
+        if (ObjectUtils.isEmpty(wechatCustomerService)) {
+            throw new SystemException("请联系管理员,配置客服");
+        }
+
+        String openKfId = wechatCustomerService.getOpenKfId();
+        WxCpKfAccountLink wxCpKfAccountLink = new WxCpKfAccountLink();
+        wxCpKfAccountLink.setOpenKfid(openKfId);
+        wxCpKfAccountLink.setScene(userName);
+        WxCpKfAccountLinkResp accountLink = wxCpKfService.getAccountLink(wxCpKfAccountLink);
+        return accountLink.getUrl();
+    }
+
+    @Override
+    public void callbackSendMsgOnEvent(WxCpXmlMessage wechatEncrypt) {
+        WxCpXmlOutMessage route = wxCpMessageRouter.route(wechatEncrypt);
+        System.out.println(route.toString());
+    }
+}

+ 20 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/WechatCustomerServiceRecordingServiceImpl.java

@@ -0,0 +1,20 @@
+package com.jzg.organization.service.impl;
+
+import com.jzg.organization.entity.WechatCustomerServiceRecording;
+import com.jzg.organization.mapper.WechatCustomerServiceRecordingMapper;
+import com.jzg.organization.service.IWechatCustomerServiceRecordingService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 微信客服记录表 服务实现类
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-17
+ */
+@Service
+public class WechatCustomerServiceRecordingServiceImpl extends ServiceImpl<WechatCustomerServiceRecordingMapper, WechatCustomerServiceRecording> implements IWechatCustomerServiceRecordingService {
+
+}

+ 87 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/WechatCustomerServiceServiceImpl.java

@@ -0,0 +1,87 @@
+package com.jzg.organization.service.impl;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jzg.commons.util.MinioUtils;
+import com.jzg.organization.entity.WechatCustomerService;
+import com.jzg.organization.entity.dto.WechatCustomerServicePageDto;
+import com.jzg.organization.entity.vo.WechatCustomerServicePageVo;
+import com.jzg.organization.entity.vo.WechatCustomerServiceQueryVo;
+import com.jzg.organization.entity.vo.WechatCustomerServiceVo;
+import com.jzg.organization.mapper.WechatCustomerServiceMapper;
+import com.jzg.organization.service.IWechatCustomerServiceDutyService;
+import com.jzg.organization.service.IWechatCustomerServiceService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * <p>
+ * 服务实现类
+ * </p>
+ *
+ * @author wenks
+ * @since 2025-09-16
+ */
+@Service
+@RequiredArgsConstructor
+public class WechatCustomerServiceServiceImpl extends ServiceImpl<WechatCustomerServiceMapper, WechatCustomerService> implements IWechatCustomerServiceService {
+
+    private final IWechatCustomerServiceDutyService wechatCustomerServiceDutyService;
+
+    private final MinioUtils minioUtils;
+
+    private final StringRedisTemplate redisTemplate;
+
+    @Override
+    public void deleteAllInfo(Long customerServiceId) {
+        removeById(customerServiceId);
+        wechatCustomerServiceDutyService.clearCustomerDuty(customerServiceId);
+    }
+
+
+    @Override
+    public Page<WechatCustomerServicePageVo> pageQuery(WechatCustomerServiceQueryVo wechatCustomerServiceQueryVo) {
+        Page<WechatCustomerServicePageDto> page = new Page<>(wechatCustomerServiceQueryVo.getPageNum(), wechatCustomerServiceQueryVo.getPageSize());
+
+        Page<WechatCustomerServicePageDto> wechatCustomerServicePageDtoPage = baseMapper.pageQuery(page, wechatCustomerServiceQueryVo);
+        List<WechatCustomerServicePageVo> list = wechatCustomerServicePageDtoPage.getRecords().stream().map(servicePageDto -> {
+            WechatCustomerServicePageVo wechatCustomerServicePageVo = new WechatCustomerServicePageVo(servicePageDto);
+            if (StringUtils.hasLength(servicePageDto.getFileName()) && minioUtils.isObjectExist(servicePageDto.getBucketName(), servicePageDto.getFileName())) {
+                wechatCustomerServicePageVo.setAvatar(MinioUtils.getPresignedObjectUrl(servicePageDto.getBucketName(), servicePageDto.getFileName()));
+            }
+            return wechatCustomerServicePageVo;
+        }).toList();
+
+        return new Page<WechatCustomerServicePageVo>(wechatCustomerServicePageDtoPage.getCurrent(), wechatCustomerServicePageDtoPage.getSize(), wechatCustomerServicePageDtoPage.getTotal())
+                .setRecords(list);
+
+    }
+
+    @Override
+    public WechatCustomerService getCacheCustomerId(WechatCustomerService wechatCustomerService) {
+        final String KEY = "sys:wechat:customer:";
+        String customerCache = redisTemplate.opsForValue().get(KEY);
+        String s1 = Optional.ofNullable(customerCache)
+                .orElse("0");
+        wechatCustomerService = lambdaQuery()
+                .gt(StringUtils.hasLength(s1), WechatCustomerService::getId, s1)
+                .orderByAsc(WechatCustomerService::getId)
+                .last("limit 1")
+                .one();
+
+        if (ObjectUtils.isEmpty(wechatCustomerService)) {
+            wechatCustomerService = lambdaQuery()
+                    .orderByAsc(WechatCustomerService::getId)
+                    .last("limit 1")
+                    .one();
+        }
+        redisTemplate.opsForValue().set(KEY, String.valueOf(wechatCustomerService.getId()));
+        return wechatCustomerService;
+    }
+}

+ 3 - 0
tenant/organization/src/main/resources/application.yml

@@ -87,6 +87,9 @@ tenant:
     - esm_user_referrer
     - sys_user_account
     - ins_ply_income_invoice_settlement_file
+    - wechat_customer_service
+    - wechat_customer_service_duty
+    - wechat_customer_service_recording
 
 
   ignoreLoginNames:

+ 5 - 0
tenant/organization/src/main/resources/mapper/SysHolidaysMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jzg.organization.mapper.SysHolidaysMapper">
+
+</mapper>

+ 5 - 0
tenant/organization/src/main/resources/mapper/WechatCustomerServiceDutyMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jzg.organization.mapper.WechatCustomerServiceDutyMapper">
+
+</mapper>

+ 30 - 0
tenant/organization/src/main/resources/mapper/WechatCustomerServiceMapper.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jzg.organization.mapper.WechatCustomerServiceMapper">
+
+    <select id="pageQuery" resultType="com.jzg.organization.entity.dto.WechatCustomerServicePageDto">
+        SELECT
+        wcs.id AS id,
+        MAX(suf.file_name) AS fileName,
+        MAX(suf.bucket_name) AS bucketName,
+        MAX(wcs.nickname) AS nickname,
+        MAX(wcs.receptionist) AS receptionist,
+        MAX(wcs.receptionist_id) AS receptionistId,
+        MAX(su.id) AS userId,
+        MAX(su.username) AS userName,
+        MAX(wcs.create_time) AS createTime,
+        MAX(IF(wcsd.id IS NOT NULL, TRUE, FALSE)) AS isScheduling
+        FROM wechat_customer_service wcs
+        LEFT JOIN sys_user su ON wcs.user_id = su.id
+        LEFT JOIN sys_upload_files suf ON wcs.avatar = suf.id
+        LEFT JOIN wechat_customer_service_duty wcsd
+        ON wcs.id = wcsd.customer_service_id
+        <where>
+            <if test="sysWechatCustomerQuery.nickname != null and sysWechatCustomerQuery.nickname != ''">
+                and wcs.nickname like concat('%', #{sysWechatCustomerQuery.nickname}, '%')
+            </if>
+        </where>
+        GROUP BY wcs.id
+    </select>
+
+</mapper>

+ 5 - 0
tenant/organization/src/main/resources/mapper/WechatCustomerServiceRecordingMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jzg.organization.mapper.WechatCustomerServiceRecordingMapper">
+
+</mapper>