فهرست منبع

add 车票工单;企业微信客户群二维码

zoujiajian 3 سال پیش
والد
کامیت
102b2b82e7
21فایلهای تغییر یافته به همراه605 افزوده شده و 25 حذف شده
  1. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpGroupChatMapper.java
  2. 2 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CmsUser.java
  3. 24 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CorpGroupChat.java
  4. 34 1
      netflix-dao/src/main/java/com/cyksj/model/entity/WorkOrder.java
  5. 84 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelWorkOrderData.java
  6. 4 2
      netflix-dao/src/main/java/com/cyksj/model/request/WorkOrderReq.java
  7. 3 0
      netflix-dao/src/main/java/com/cyksj/model/views/CmsUserVO.java
  8. 3 0
      netflix-dao/src/main/java/com/cyksj/model/views/GroupRelationDetailView.java
  9. 3 0
      netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java
  10. 51 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserWorkOrderView.java
  11. 15 0
      netflix-dao/src/main/java/com/cyksj/model/views/WorkOrderView.java
  12. 1 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  13. 24 0
      netflix-service/src/main/java/com/cyksj/service/corp/CropChatService.java
  14. 8 0
      netflix-service/src/main/java/com/cyksj/service/corp/WxCorpOps.java
  15. 72 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CropChatServiceImpl.java
  16. 95 1
      netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java
  17. 30 5
      netflix-service/src/main/java/com/cyksj/service/user/impl/WorkOrderFrontServiceImpl.java
  18. 64 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpChatController.java
  19. 56 7
      netflix-web/src/main/java/com/cyksj/web/controller/manage/sys/WorkOrderController.java
  20. 19 9
      netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java
  21. 0 0
      netflix-web/src/main/resources/application-prd.yml

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpGroupChatMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.corp;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CorpGroupChat;
+
+/*
+ *项目名: netflix
+ *文件名: CorpGroupChatMapper
+ *创建者: JavaZou
+ *创建时间:2023/6/26 17:37
+ */
+public interface CorpGroupChatMapper extends BaseMapper<CorpGroupChat> {
+}

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CmsUser.java

@@ -43,6 +43,8 @@ public class CmsUser extends BaseEntity{
 	 */
 	private String modifiedBy;
 
+	private String authId;
+
 
 	/**
 	 * 管理员是否允许登录

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpGroupChat.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: CorpGroupChat
+ *创建者: JavaZou
+ *创建时间:2023/6/26 17:36
+ */
+@Getter
+@Setter
+public class CorpGroupChat extends BaseEntity{
+	private String chatId;
+
+	private String chatName;
+
+	private Long wxCorpId;
+
+	private Long goodsId;
+
+	private String configId;
+}

+ 34 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/WorkOrder.java

@@ -20,22 +20,55 @@ public class WorkOrder extends BaseEntity{
 
 	private Long relationId;
 
+	private Long accountId;
+
+	private String account;
+
 	private Long goodsId;
 
 	private Long skuId;
 
 	private Status status;
 
+	/**
+	 * 分配的客服id
+	 */
+	private Long assignCustomerServiceId;
+
 	private Long closeCustomerServiceId;
 
+	/**
+	 * 客服凭证id
+	 */
+	private String customerServiceAuthId;
+
+	private Type type;
+
+
+	@Getter
+	public enum Type {
+		freeze("账号被封"),
+		noMember("无会员"),
+		;
+
+		String desc;
+
+		Type(String desc) {
+			this.desc = desc;
+		}
+	}
+
 	@Getter
 	public enum Status {
 		waiting("待处理"),
-		close("已关闭");
+		close("已关闭"),
+		normal("无异常"),
+		;
 
 		String desc;
 
 		Status(String desc) {
+			this.desc = desc;
 		}
 	}
 }

+ 84 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelWorkOrderData.java

@@ -0,0 +1,84 @@
+package com.cyksj.model.excel;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.cyksj.model.entity.WorkOrder;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: ExcelWorkOrderData
+ *创建者: JavaZou
+ *创建时间:2023/6/26 15:19
+ */
+@Getter
+@Setter
+@SearchBean(tables = "work_order wo left join user u on u.id = wo.user_id" +
+		" left join goods_don g on g.id = wo.goods_id" +
+		" left join goods_don_sku sku on sku.id = wo.sku_id")
+public class ExcelWorkOrderData {
+	@DbField("wo.id")
+	@ExcelIgnore
+	private Long id;
+
+	@DbField("wo.account")
+	@ExcelProperty("账号")
+	private String account;
+
+	@DbField("g.title")
+	@ExcelProperty("平台")
+	private String title;
+
+	@DbField("sku.spec_val")
+	@ExcelProperty("规格")
+	private String specVal;
+
+	@DbField("wo.user_id")
+	@ExcelProperty("用户ID")
+	private Long userId;
+
+	@DbField("select nickname from user where id = wo.user_id limit 1")
+	@ExcelProperty("用户名")
+	private String nickname;
+
+	@DbField("wo.type")
+	@ExcelIgnore
+	private WorkOrder.Type type;
+
+	@DbField("wo.assign_customer_service_id")
+	@ExcelIgnore
+	private Long assignCustomerServiceId;
+
+	@DbField("wo.status")
+	@ExcelIgnore
+	private WorkOrder.Status status;
+
+	@DbIgnore
+	@ExcelProperty("问题类型")
+	private String questionType;
+
+	@DbIgnore
+	@ExcelProperty("问题状态")
+	private String questionStatus;
+
+	@DbField("wo.created_time")
+	@ExcelProperty("提交时间")
+	private Date createdTime;
+
+	public String getQuestionType() {
+		if (type == null) return StrUtil.EMPTY;
+		return type.getDesc();
+	}
+
+	public String getQuestionStatus() {
+		if (status == null) return StrUtil.EMPTY;
+		return status.getDesc();
+	}
+}

+ 4 - 2
netflix-dao/src/main/java/com/cyksj/model/request/WorkOrderReq.java

@@ -1,9 +1,9 @@
 package com.cyksj.model.request;
 
+import com.cyksj.model.entity.WorkOrder;
 import lombok.Getter;
 import lombok.Setter;
 
-import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
 
 /*
@@ -17,12 +17,14 @@ import javax.validation.constraints.NotNull;
 public class WorkOrderReq {
 	private Long userId;
 
-	@NotEmpty(message = "请输入工单主题")
 	private String topic;
 
 	@NotNull(message = "请选择车票")
 	private Long relationId;
 
+	@NotNull(message = "请选择对应问题类型")
+	private WorkOrder.Type type;
+
 	private String content;
 
 	private String imgs;

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CmsUserVO.java

@@ -60,6 +60,9 @@ public class CmsUserVO {
 	@DbField("cu.modified_by")
 	private String modifiedBy;
 
+	@DbField("cu.auth_id")
+	private String authId;
+
 	/**
 	 * 权限列表
 	 */

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GroupRelationDetailView.java

@@ -27,4 +27,7 @@ public class GroupRelationDetailView {
 
 	@DbField("gdk.goods_id")
 	private Long goodsId;
+
+	@DbField("gt.account_Id")
+	private Long accountId;
 }

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java

@@ -38,6 +38,9 @@ public class RenewalView {
     @DbField("sku.price")
     private BigDecimal price;
 
+    @DbField("sku.spec_val")
+    private String specVal;
+
     @DbField("gr.id")
     private Long relationId;
 

+ 51 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserWorkOrderView.java

@@ -0,0 +1,51 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.WorkOrder;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: UserWorkOrderView
+ *创建者: JavaZou
+ *创建时间:2023/6/26 9:56
+ */
+@Getter
+@Setter
+@SearchBean(tables = "work_order wo left join goods_don g on g.id = wo.goods_id" +
+		" left join goods_don_sku sku on sku.id = wo.sku_id")
+public class UserWorkOrderView {
+
+	@DbField("wo.user_id")
+	@JsonIgnore
+	private Long userId;
+
+	@DbField("wo.account")
+	private String account;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("g.logo")
+	private String logo;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("wo.type")
+	private WorkOrder.Type type;
+
+	@DbField("wo.status")
+	private WorkOrder.Status status;
+
+	@DbField("wo.created_time")
+	private Date createdTime;
+
+	@DbField("wo.customer_service_auth_id")
+	private String customerServiceAuthId;
+}

+ 15 - 0
netflix-dao/src/main/java/com/cyksj/model/views/WorkOrderView.java

@@ -25,6 +25,9 @@ public class WorkOrderView {
 	@DbField("wo.user_id")
 	private Long userId;
 
+	@DbField("wo.assign_customer_service_id")
+	private Long assignCustomerServiceId;
+
 	@DbField("wo.reply_customer_service_id")
 	private Long replyCustomerServiceId;
 
@@ -64,6 +67,18 @@ public class WorkOrderView {
 	@DbField("wo.topic")
 	private String topic;
 
+	@DbField("wo.type")
+	private WorkOrder.Type type;
+
+	@DbField("wo.account_id")
+	private Long accountId;
+
+	@DbField("wo.account")
+	private String account;
+
+	@DbField("wo.customer_service_auth_id")
+	private String customerServiceAuthId;
+
 	@DbField("wo.status")
 	private WorkOrder.Status status;
 

+ 1 - 0
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -610,6 +610,7 @@ public class RedisService {
         IMPORT_ACCOUNT_CACHE_KEY("import_account_cache_key:%s", "导入缓存key", 60 * 10L),
         MAKERTING_MSG_KEY("makerting_msg_key", "营销短信", 60 * 60 * 24 * 30),
         PHONE_AREA_CODE("phone_area_code:key", "国家或地区码", 60 * 60 * 24 * 15),
+        CORP_CHAT_GROUP_CODE("corp_chat_group_code:", "企业微信群动态码", 60 * 60 * 24 * 15),
         ;
 
         private String name;

+ 24 - 0
netflix-service/src/main/java/com/cyksj/service/corp/CropChatService.java

@@ -0,0 +1,24 @@
+package com.cyksj.service.corp;
+
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: CropChatService
+ *创建者: JavaZou
+ *创建时间:2023/6/26 16:26
+ */
+public interface CropChatService {
+	void getCorpChat(String corpId, String configId) throws Exception;
+
+	String getGroupsList() throws Exception;
+
+	/**
+	 * 设置企业微信群配置
+	 */
+	void setGroupsConfig(List<String> chatIds) throws Exception;
+
+	String getGroupsDetail(String chatId) throws Exception;
+
+	String getCropWxChatGroupByGoodsId(Long goodsId) throws Exception;
+}

+ 8 - 0
netflix-service/src/main/java/com/cyksj/service/corp/WxCorpOps.java

@@ -74,4 +74,12 @@ public interface WxCorpOps {
 	 * 企业微信获取应用js_ticket
 	 */
 	String getAgentJsTicket(String corpId, String agentId) throws Exception;
+
+	String getCorpChatGroups(String corpId,String config) throws Exception;
+
+	String getGroupsList() throws Exception;
+
+	String setGroupsConfig(List<String> chatIds) throws Exception;
+
+	String getGroupsDetail(String chatId) throws Exception;
 }

+ 72 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CropChatServiceImpl.java

@@ -0,0 +1,72 @@
+package com.cyksj.service.corp.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.corp.CorpGroupChatMapper;
+import com.cyksj.mapper.corp.WxCorpAppMapper;
+import com.cyksj.model.entity.CorpGroupChat;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.corp.CropChatService;
+import com.cyksj.service.corp.WxCorpOps;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: CropChatServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/6/26 16:26
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class CropChatServiceImpl implements CropChatService {
+	private final WxCorpOps wxCorpOps;
+
+	private final WxCorpAppMapper wxCorpAppMapper;
+
+	private final CorpGroupChatMapper corpGroupChatMapper;
+
+	private final RedisService redisService;
+
+	@Override
+	public void getCorpChat(String corpId, String configId) throws Exception {
+		wxCorpOps.getCorpChatGroups(corpId,configId);
+	}
+
+	@Override
+	public String getGroupsList() throws Exception {
+		return wxCorpOps.getGroupsList();
+	}
+
+	@Override
+	public void setGroupsConfig(List<String> chatIds) throws Exception {
+		String body = wxCorpOps.setGroupsConfig(chatIds);
+		//记录 企业客户群的配置id
+		System.out.println(body);
+	}
+
+	@Override
+	public String getGroupsDetail(String chatId) throws Exception {
+		return wxCorpOps.getGroupsDetail(chatId);
+	}
+
+	@Override
+	public String getCropWxChatGroupByGoodsId(Long goodsId) throws Exception {
+		String configId = redisService.getStr(RedisService.key.CORP_CHAT_GROUP_CODE.getName() + goodsId);
+		if (StrUtil.isBlank(configId)) {
+			CorpGroupChat corpGroupChat = corpGroupChatMapper.selectOne(Wrappers.lambdaQuery(CorpGroupChat.class)
+					.eq(CorpGroupChat::getGoodsId, goodsId).last("limit 1"));
+			if (corpGroupChat == null) {
+				throw BusinessRuntimeException.getInstance("");
+			}
+			configId = corpGroupChat.getConfigId();
+		}
+		redisService.setNx(RedisService.key.CORP_CHAT_GROUP_CODE.getName() + goodsId, configId, RedisService.key.CORP_CHAT_GROUP_CODE.getTimeout());
+		return wxCorpOps.getCorpChatGroups(null, configId);
+	}
+}

+ 95 - 1
netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java

@@ -23,6 +23,7 @@ import java.net.URLEncoder;
 import java.net.http.HttpRequest;
 import java.net.http.HttpResponse;
 import java.util.List;
+import java.util.Optional;
 
 /*
  *项目名: netflix
@@ -57,7 +58,7 @@ public class WxCorpOpsImpl implements WxCorpOps {
 
 	@Override
 	public String getAccessToken(String corpId) throws Exception {
-		String accessToken = redisService.getStr(RedisKey.CORP_ACCESS_TOKEN_KEY + corpId);
+		String accessToken = StrUtil.EMPTY;
 		if (StringUtils.isNotBlank(accessToken)) {
 			return accessToken;
 		}
@@ -185,6 +186,99 @@ public class WxCorpOpsImpl implements WxCorpOps {
 		return ticket;
 	}
 
+	@Override
+	public String getCorpChatGroups(String corpId, String configId) throws Exception {
+		corpId = Optional.ofNullable(corpId).orElse(yhlXWxCorpConfig.getCorpId());
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/get_join_way?access_token=" + getAccessToken(corpId);
+		JSONObject jsonObject = new JSONObject();
+		jsonObject.putOpt("config_id", configId);
+		HttpResponse<byte[]> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.cacheURI()
+						.body(HttpRequest.BodyPublishers.ofString(jsonObject.toString(), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofByteArray());
+		String body = IoKit.toString(res.body());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("获取access_token失败: " + body);
+		}
+		JSONObject re = Jsons.parseObject(body, JSONObject.class);
+		Integer errcode = re.getInt("errcode");
+		if (null != errcode && 0 != errcode) {
+			throw BusinessRuntimeException.getInstance("获取企业微信access_token失败: " + re.getStr("errmsg") + "[" + errcode + "]");
+		}
+		JSONObject codeRe = Jsons.parseObject(re.getStr("join_way"), JSONObject.class);
+		String qr_code = codeRe.getStr("qr_code");
+		return qr_code;
+	}
+
+	@Override
+	public String getGroupsList() throws Exception {
+		String corpId = yhlXWxCorpConfig.getCorpId();
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/list?access_token=" + getAccessToken(corpId);
+		JSONObject jsonObject = new JSONObject();
+		jsonObject.putOpt("limit", 1000);
+		HttpResponse<byte[]> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.cacheURI()
+						.body(HttpRequest.BodyPublishers.ofString(jsonObject.toString(), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofByteArray());
+		String body = IoKit.toString(res.body());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("获取access_token失败: " + IoKit.toString(res.body()));
+		}
+		return body;
+	}
+
+	@Override
+	public String setGroupsConfig(List<String> chatIds) throws Exception {
+		String corpId = yhlXWxCorpConfig.getCorpId();
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/add_join_way?access_token=" + getAccessToken(corpId);
+		JSONObject jsonObject = new JSONObject();
+		//scene	是	场景。
+		//1 - 群的小程序插件
+		//2 - 群的二维码插件
+		jsonObject.putOpt("scene", 2);
+		jsonObject.putOpt("chat_id_list", chatIds);
+		jsonObject.putOpt("room_base_name", "Ai银河课堂 MJ SD教程分享");
+		HttpResponse<byte[]> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.cacheURI()
+						.body(HttpRequest.BodyPublishers.ofString(jsonObject.toString(), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofByteArray());
+		String body = IoKit.toString(res.body());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("获取access_token失败: " + body);
+		}
+		log.info("配置企业微信群返回信息body:{}", body);
+		return body;
+	}
+
+	@Override
+	public String getGroupsDetail(String chatId) throws Exception {
+		String corpId = yhlXWxCorpConfig.getCorpId();
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/get?access_token=" + getAccessToken(corpId);
+		JSONObject jsonObject = new JSONObject();
+		jsonObject.putOpt("chat_id", chatId);
+		HttpResponse<byte[]> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.cacheURI()
+						.body(HttpRequest.BodyPublishers.ofString(jsonObject.toString(), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofByteArray());
+		String body = IoKit.toString(res.body());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("获取access_token失败: " + body);
+		}
+		return body;
+	}
+
 	public String access_token(String corpId) throws Exception {
 		WxCorpApp wxCorpApp = WeChatCorpFactory.getCorpConfigStrategy(corpId);
 		if (corpId == null) {

+ 30 - 5
netflix-service/src/main/java/com/cyksj/service/user/impl/WorkOrderFrontServiceImpl.java

@@ -1,15 +1,19 @@
 package com.cyksj.service.user.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.enums.GatewayApiCode;
+import com.cyksj.mapper.AccountMapper;
 import com.cyksj.mapper.manage.sys.WorkOrderChatHistoryMapper;
 import com.cyksj.mapper.manage.sys.WorkOrderMapper;
 import com.cyksj.model.entity.User;
 import com.cyksj.model.entity.WorkOrder;
 import com.cyksj.model.entity.WorkOrderChatHistory;
 import com.cyksj.model.request.WorkOrderReq;
+import com.cyksj.model.views.CmsUserVO;
 import com.cyksj.model.views.GroupRelationDetailView;
 import com.cyksj.service.user.UserService;
 import com.cyksj.service.user.WorkOrderFrontService;
@@ -22,6 +26,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
+import java.util.Optional;
 
 /*
  *项目名: netflix
@@ -41,26 +46,33 @@ public class WorkOrderFrontServiceImpl implements WorkOrderFrontService {
 
 	private final UserService userService;
 
+	private final AccountMapper accountMapper;
+
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	public void submitWorkOrder(WorkOrderReq workOrderReq) {
 		Long userId = workOrderReq.getUserId();
+		Long relationId = workOrderReq.getRelationId();
+		//是否已提交过该工单
+		WorkOrder exists = workOrderMapper.selectOne(Wrappers.lambdaQuery(WorkOrder.class)
+				.eq(WorkOrder::getRelationId, relationId)
+				.eq(WorkOrder::getUserId, userId)
+				.last("limit 1"));
+		if (exists != null) {
+			throw BusinessRuntimeException.getInstance("您已提交过该车票工单");
+		}
 		User user = userService.getById(userId);
 		if (user == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
 		String content = workOrderReq.getContent();
 		String imgs = workOrderReq.getImgs();
-		if (StrUtil.isEmpty(content) && StrUtil.isEmpty(imgs)) {
-			throw BusinessRuntimeException.getInstance("请输入相关内容");
-		}
 		String topic = workOrderReq.getTopic();
-		if (topic.length() > 32) {
+		if (StrUtil.isNotBlank(topic) && topic.length() > 32) {
 			throw BusinessRuntimeException.getInstance("标题最多输入30字数以内");
 		}
 		if (StrUtil.isNotBlank(content) && content.length() > 200) {
 			throw BusinessRuntimeException.getInstance("问题描述最多输入200字数以内");
 		}
 		List<Long> userIds = userService.getRelationUserIdList(userId, user);
-		Long relationId = workOrderReq.getRelationId();
 		GroupRelationDetailView detailView = beanSearcher.searchFirst(GroupRelationDetailView.class, MapUtils.builder()
 				.field(GroupRelationDetailView::getUserId, userIds).op(Operator.InList)
 				.field(GroupRelationDetailView::getRelationId, relationId)
@@ -71,6 +83,19 @@ public class WorkOrderFrontServiceImpl implements WorkOrderFrontService {
 		BeanUtil.copyProperties(workOrderReq, workOrder);
 		workOrder.setGoodsId(detailView.getGoodsId());
 		workOrder.setSkuId(detailView.getSkuId());
+		Optional.ofNullable(accountMapper.selectById(detailView.getAccountId()))
+				.ifPresent(account -> {
+					workOrder.setAccountId(detailView.getAccountId());
+					workOrder.setAccount(account.getAccount());
+				});
+		//随机分配给客服
+		List<CmsUserVO> customers = beanSearcher.searchAll(CmsUserVO.class, MapUtils.builder().field(CmsUserVO::getRoleNames, "客服").op(Operator.Contain).build());
+		if (customers.size() > 0) {
+			int randomIndex = RandomUtil.randomInt(customers.size());
+			CmsUserVO customer = customers.get(randomIndex);
+			workOrder.setAssignCustomerServiceId(customer.getId());
+			workOrder.setCustomerServiceAuthId(customer.getAuthId());
+		}
 		workOrderMapper.insert(workOrder);
 
 		WorkOrderChatHistory workOrderChatHistory = new WorkOrderChatHistory();

+ 64 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpChatController.java

@@ -0,0 +1,64 @@
+package com.cyksj.web.controller.manage.corp;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.service.corp.CropChatService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: CorpChatController
+ *创建者: JavaZou
+ *创建时间:2023/6/26 16:24
+ */
+@RestController
+@RequestMapping("/manage/corpChat")
+@RequiredArgsConstructor
+public class CorpChatController {
+	private final CropChatService cropChatService;
+
+	/**
+	 * 客户群列表
+	 */
+	@GetMapping("/get/groups/list")
+	public Result<String> getGroupsList() throws Exception {
+		String body = cropChatService.getGroupsList();
+		return GatewayResponse.SUCCESS.newBuilder().toResult(body);
+	}
+
+	/**
+	 * 客户群详情
+	 */
+	@GetMapping("/get/groups/detail")
+	public Result<String> getGroupsDetail(String chatId) throws Exception {
+		String body = cropChatService.getGroupsDetail(chatId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(body);
+	}
+
+	/**
+	 * 客户群配置列表
+	 */
+	@GetMapping("/get/config/list")
+	public Result<String> getCorpChat(String corpId,String configId) throws Exception {
+		cropChatService.getCorpChat(corpId, configId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+
+	/**
+	 * 配置客户群
+	 */
+	@PostMapping("/set/group")
+	public Result<String> setGroupsConfig(@RequestBody List<String> chatIds) throws Exception {
+		cropChatService.setGroupsConfig(chatIds);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+}
+
+
+
+

+ 56 - 7
netflix-web/src/main/java/com/cyksj/web/controller/manage/sys/WorkOrderController.java

@@ -3,6 +3,7 @@ package com.cyksj.web.controller.manage.sys;
 import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.support.ExcelTypeEnum;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
@@ -14,10 +15,15 @@ import com.cyksj.mapper.manage.sys.WorkOrderChatHistoryMapper;
 import com.cyksj.mapper.manage.sys.WorkOrderMapper;
 import com.cyksj.model.entity.WorkOrder;
 import com.cyksj.model.entity.WorkOrderChatHistory;
+import com.cyksj.model.excel.ExcelWorkOrderData;
+import com.cyksj.model.views.CmsUserVO;
 import com.cyksj.model.views.WorkOrderChatHistoryView;
 import com.cyksj.model.views.WorkOrderView;
+import com.cyksj.web.util.EasyExcelUtils;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
@@ -26,6 +32,8 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
 import java.util.Optional;
 
 /*
@@ -54,8 +62,22 @@ public class WorkOrderController {
 
 	@GetMapping("/get")
 	@SaCheckPermission("workOrder:view")
-	public Result<SearchResult<WorkOrderView>> getWorkOrderList() {
-		SearchResult<WorkOrderView> search = beanSearcher.search(WorkOrderView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+	public Result<SearchResult<WorkOrderView>> getWorkOrderList(String nickname) {
+		long adminId = StpUtil.getLoginIdAsLong();
+		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+		//是不是客服
+		CmsUserVO isCustomer = beanSearcher.searchFirst(CmsUserVO.class, MapUtils.builder()
+				.field(CmsUserVO::getRoleNames, "客服").op(Operator.Contain)
+				.field(CmsUserVO::getId, adminId)
+				.build());
+		if (isCustomer != null) {
+			builder.field(WorkOrderView::getAssignCustomerServiceId, isCustomer.getId());
+		}
+		if (StrUtil.isNotBlank(nickname)) {
+			List<Long> userIds = userMapper.selectListByNickname(nickname);
+			builder.field(WorkOrderView::getUserId, userIds).op(Operator.InList);
+		}
+		SearchResult<WorkOrderView> search = beanSearcher.search(WorkOrderView.class, builder.build());
 		search.getDataList().forEach(data -> {
 			Optional.ofNullable(goodsDonMapper.selectById(data.getGoodsId()))
 					.ifPresent(goodsDon -> data.setTitle(goodsDon.getTitle()));
@@ -78,22 +100,22 @@ public class WorkOrderController {
 	 */
 	@PutMapping("/put/{id}")
 	@SaCheckPermission("workOrder:updateStatus")
-	public Result<String> putWorkOrderStatus(@PathVariable Long id) {
+	public Result<String> putWorkOrderStatus(@PathVariable Long id, WorkOrder.Status status) {
 		long adminId = StpUtil.getLoginIdAsLong();
 		WorkOrder workOrder = workOrderMapper.selectById(id);
 
 		if (workOrder == null) {
 			throw BusinessRuntimeException.getInstance("该工单不存在");
 		}
-		if (workOrder.getStatus() == WorkOrder.Status.close) {
-			throw BusinessRuntimeException.getInstance("该工单已关闭");
+		if (workOrder.getStatus() != WorkOrder.Status.waiting) {
+			throw BusinessRuntimeException.getInstance("该工单已处理");
 		}
 		if (workOrder.getCloseCustomerServiceId() == 0) {
 			workOrder.setCloseCustomerServiceId(adminId);
 		}
-		workOrder.setStatus(WorkOrder.Status.close);
+		workOrder.setStatus(status);
 		workOrderMapper.updateById(workOrder);
-		return GatewayResponse.SUCCESS.newBuilder().toResult("关闭成功");
+		return GatewayResponse.SUCCESS.newBuilder().toResult("处理成功");
 	}
 
 	/**
@@ -152,4 +174,31 @@ public class WorkOrderController {
 		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
+
+	/**
+	 * 导出工单
+	 */
+	@GetMapping("/export")
+	public void export(String nickname, String ids, HttpServletResponse response) {
+		long adminId = StpUtil.getLoginIdAsLong();
+		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+		//是不是客服
+		CmsUserVO isCustomer = beanSearcher.searchFirst(CmsUserVO.class, MapUtils.builder()
+				.field(CmsUserVO::getRoleNames, "客服").op(Operator.Contain)
+				.field(CmsUserVO::getId, adminId)
+				.build());
+		if (StrUtil.isNotBlank(ids)) {
+			String[] idAr = ids.split(",");
+			builder.field(ExcelWorkOrderData::getId, idAr).op(Operator.InList);
+		}
+		if (isCustomer != null) {
+			builder.field(ExcelWorkOrderData::getAssignCustomerServiceId, isCustomer.getId());
+		}
+		if (StrUtil.isNotBlank(nickname)) {
+			List<Long> userIds = userMapper.selectListByNickname(nickname);
+			builder.field(WorkOrderView::getUserId, userIds).op(Operator.InList);
+		}
+		List<ExcelWorkOrderData> list = beanSearcher.searchAll(ExcelWorkOrderData.class, builder.build());
+		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelWorkOrderData.class, list, "用户工单", "用户工单", ExcelTypeEnum.XLSX, null);
+	}
 }

+ 19 - 9
netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java

@@ -17,10 +17,8 @@ import com.cyksj.model.request.ExchangeCodeTicket;
 import com.cyksj.model.request.ReceiveBenefitsReq;
 import com.cyksj.model.request.UserReq;
 import com.cyksj.model.request.WorkOrderReq;
-import com.cyksj.model.views.RenewalView;
-import com.cyksj.model.views.UserAvailableGoodsTicketView;
-import com.cyksj.model.views.UserPersonalView;
-import com.cyksj.model.views.WorkOrderChatHistoryView;
+import com.cyksj.model.views.*;
+import com.cyksj.service.corp.CropChatService;
 import com.cyksj.service.exchange.ExchangeCodeService;
 import com.cyksj.service.order.UserRealOrderBenefitsService;
 import com.cyksj.service.relation.GroupRelationFrontService;
@@ -66,6 +64,8 @@ public class UserController {
 
     private final HttpServletRequest request;
 
+    private final CropChatService cropChatService;
+
     @GetMapping(value = "/wx/whoami")
     public Result<UserWhoami> whoami() {
         long userId = StpUserUtil.getLoginIdAsLong();
@@ -160,12 +160,11 @@ public class UserController {
      * 用户工单历史列表
      */
     @GetMapping("/workOrder/get")
-    public Result<SearchResult<WorkOrder>> getWorkOrder() {
+    public Result<SearchResult<UserWorkOrderView>> getWorkOrder() {
         long userId = StpUserUtil.getLoginIdAsLong();
-        SearchResult<WorkOrder> search = beanSearcher.search(WorkOrder.class, MapUtils.flatBuilder(request.getParameterMap())
-                .field(WorkOrder::getUserId, userId)
-                .orderBy(WorkOrder::getId).desc()
-                .onlySelect(WorkOrder::getId, WorkOrder::getTopic, WorkOrder::getStatus, WorkOrder::getCreatedTime)
+        SearchResult<UserWorkOrderView> search = beanSearcher.search(UserWorkOrderView.class, MapUtils.flatBuilder(request.getParameterMap())
+                .field(UserWorkOrderView::getUserId, userId)
+                .orderBy(UserWorkOrderView::getCreatedTime).desc()
                 .build());
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
@@ -272,4 +271,15 @@ public class UserController {
                 .last("limit 1"));
         return GatewayResponse.SUCCESS.newBuilder().toResult(user);
     }
+
+    /**
+     * 获取群聊二维码
+     */
+    @GetMapping("/get/corp/ChatCode/{goodsId}")
+    public Result<String> getCorpChatCode(@PathVariable Long goodsId) throws Exception {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        //获取对应产品的企业微信客户群
+        String qrCode = cropChatService.getCropWxChatGroupByGoodsId(goodsId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(qrCode);
+    }
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
netflix-web/src/main/resources/application-prd.yml


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است