Przeglądaj źródła

Merge remote-tracking branch 'origin/master'

zoujiajian 8 miesięcy temu
rodzic
commit
4d982f5ed2

+ 10 - 0
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -277,6 +277,11 @@ public interface Constant {
 	 */
 	Integer NF_RECOVER_STANDBY_JOB_ID = 321;
 
+	/**
+	 * 奈飞脆球同步邮件数据任务id
+	 */
+	Integer NF_CUI_QIU_EMAIL_SYNC_JOB_ID = 331;
+
 	String ACCOUNT_PWD_UPDATE_SYS_MSG_NOTIFY = "您购买的%s账号,密码已修改";
 
 	String ACCOUNT_SET_SYS_MSG_NOTIFY = "您购买的%s账号,账号已配置";
@@ -740,4 +745,9 @@ public interface Constant {
 	 * 实物支付商户id
 	 */
 	String REAL_GOODS_PAY_SHOP_ID = "real_goods_pay_shop_id";
+
+	/**
+	 * gpt车队id
+	 */
+	String GPT_CARD_ID = "P288";
 }

+ 9 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GptQuickLinkRecordMapper.java

@@ -0,0 +1,9 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GptQuickLinkRecord;
+
+
+public interface GptQuickLinkRecordMapper extends BaseMapper<GptQuickLinkRecord> {
+
+}

+ 49 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CuiQiuEmailInfoRecord.java

@@ -0,0 +1,49 @@
+package com.cyksj.model.entity;
+
+import com.cyksj.model.BaseEntity;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+
+@Getter
+@Setter
+public class CuiQiuEmailInfoRecord extends BaseEntity {
+	private Long goodsId;
+
+	/**
+	 * 接受主邮箱id
+	 */
+	private String mailId;
+
+	/**
+	 * 邮件id
+	 */
+	private String messageId;
+
+	/**
+	 * 邮件来源
+	 */
+	private String from;
+
+	/**
+	 * 发送邮件
+	 */
+	private String to;
+
+	/**
+	 * 邮件标题
+	 */
+	private String subject;
+
+	/**
+	 * 邮件内容
+	 */
+	private String body;
+
+	/**
+	 * 邮件发送时间
+	 */
+	private Date sendTime;
+}

+ 32 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GptQuickLinkRecord.java

@@ -0,0 +1,32 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.cyksj.model.BaseEntity;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * gpt快捷链接
+ */
+@Data
+@TableName("gpt_quick_link_record")
+@SearchBean(tables = "gpt_quick_link_record")
+public class GptQuickLinkRecord extends BaseEntity {
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 标识
+     */
+    private String code;
+
+    /**
+     * 有效期
+     */
+    private Date expiryTime;
+}

+ 71 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelCuiQiuEmailInfoRecordData.java

@@ -0,0 +1,71 @@
+package com.cyksj.model.excel;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ExcelCuiQiuEmailInfoRecordData
+ * 创建者: JavaZou
+ * 创建时间:2025/11/24 11:33
+ */
+@Getter
+@Setter
+@SearchBean(tables = "cui_qiu_email_info_record cr",
+		where = ":sl:",
+		groupBy = "cr.goods_id,cr.to,cr.subject")
+@ExcelIgnoreUnannotated
+public class ExcelCuiQiuEmailInfoRecordData {
+
+	@DbField("max(cr.id)")
+	@ExcelProperty("ID")
+	private Long id;
+
+	@DbField("cr.goods_id")
+	private Long goodsId;
+
+	/**
+	 * 接受主邮箱id
+	 */
+	@DbField("min(cr.mail_id)")
+	private String mailId;
+
+	/**
+	 * 邮件id
+	 */
+	@DbField("max(cr.message_id)")
+	private String messageId;
+
+	/**
+	 * 邮件来源
+	 */
+	@DbField("any_value(cr.from)")
+	private String from;
+
+	/**
+	 * 发送邮件
+	 */
+	@ExcelProperty("账号")
+	@DbField("cr.to")
+	private String to;
+
+	/**
+	 * 邮件标题
+	 */
+	@ExcelProperty("邮件标题")
+	@DbField("cr.subject")
+	private String subject;
+
+	/**
+	 * 邮件发送时间
+	 */
+	@ExcelProperty("邮件时间")
+	@DbField("max(cr.send_time)")
+	private Date sendTime;
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/request/AccountGroupsReq.java

@@ -64,6 +64,11 @@ public class AccountGroupsReq {
 	 */
 	private String email;
 
+	/**
+	 * 关联邮箱
+	 */
+	private String relateEmail;
+
 	/**
 	 * 激活码
 	 */

+ 34 - 0
netflix-dao/src/main/java/com/cyksj/model/response/GptQuickLinkResp.java

@@ -0,0 +1,34 @@
+package com.cyksj.model.response;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: GptQuickLinkResp
+ * 创建者: JavaZou
+ * 创建时间:2025/11/20 15:51
+ */
+@Getter
+@Setter
+public class GptQuickLinkResp {
+
+	/**
+	 * 1.成功 2.链接到期 3.车票过期 4.多张车票
+	 */
+	private Integer state;
+
+	private String url;
+
+	private String code;
+
+	private Date expiryTime;
+
+	@JsonIgnore
+	private Long userId;
+
+	private String token;
+}

+ 63 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CuiQiuEmailInfoRecordView.java

@@ -0,0 +1,63 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: CuiQiuEmailInfoRecordView
+ * 创建者: JavaZou
+ * 创建时间:2025/11/24 11:46
+ */
+@Getter
+@Setter
+@SearchBean(tables = "cui_qiu_email_info_record cr",
+		where = ":sl:",
+		groupBy = "cr.goods_id,cr.to,cr.subject")
+public class CuiQiuEmailInfoRecordView {
+	@DbField("max(cr.id)")
+	private Long id;
+
+	@DbField("cr.goods_id")
+	private Long goodsId;
+
+	/**
+	 * 接受主邮箱id
+	 */
+	@DbField("min(cr.mail_id)")
+	private String mailId;
+
+	/**
+	 * 邮件id
+	 */
+	@DbField("max(cr.message_id)")
+	private String messageId;
+
+	/**
+	 * 邮件来源
+	 */
+	@DbField("any_value(cr.from)")
+	private String from;
+
+	/**
+	 * 发送邮件
+	 */
+	@DbField("cr.to")
+	private String to;
+
+	/**
+	 * 邮件标题
+	 */
+	@DbField("cr.subject")
+	private String subject;
+
+	/**
+	 * 邮件发送时间
+	 */
+	@DbField("max(cr.send_time)")
+	private Date sendTime;
+}

+ 25 - 0
netflix-service/src/main/java/com/cyksj/service/gpt/GptQuickLinkService.java

@@ -0,0 +1,25 @@
+package com.cyksj.service.gpt;
+
+import com.cyksj.model.entity.GptQuickLinkRecord;
+import com.cyksj.model.response.GptQuickLinkResp;
+
+/**
+ * GPT快捷链接服务接口
+ */
+public interface GptQuickLinkService {
+    
+    /**
+     * 创建快捷链接
+     */
+    GptQuickLinkRecord createQuickLink(Long userId);
+    
+    /**
+     * 获取用户最新的快捷链接
+     */
+    GptQuickLinkRecord getLatestQuickLink(Long userId);
+    
+    /**
+     * 根据code获取快捷链接
+     */
+    GptQuickLinkResp getQuickUrlByCode(String code);
+}

+ 163 - 0
netflix-service/src/main/java/com/cyksj/service/gpt/impl/GptQuickLinkServiceImpl.java

@@ -0,0 +1,163 @@
+package com.cyksj.service.gpt.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.mapper.GptQuickLinkRecordMapper;
+import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.model.entity.GptQuickLinkRecord;
+import com.cyksj.model.entity.SysConfig;
+import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.model.response.GptQuickLinkResp;
+import com.cyksj.service.chatgpt.ChatGptAccountService;
+import com.cyksj.service.gpt.GptQuickLinkService;
+import com.cyksj.service.sys.SysConfigService;
+import com.cyksj.service.user.UserBindRelationService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * GPT快捷链接服务实现类
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class GptQuickLinkServiceImpl implements GptQuickLinkService {
+
+    private final GptQuickLinkRecordMapper gptQuickLinkRecordMapper;
+
+    private final GroupsRelationMapper groupsRelationMapper;
+
+    private final UserBindRelationService userBindRelationService;
+
+    private final BeanSearcher beanSearcher;
+
+    private final ChatGptAccountService chatGptAccountService;
+
+    private final SysConfigService sysConfigService;
+
+    @Override
+    public GptQuickLinkRecord createQuickLink(Long userId) {
+        // 检查用户是否有GPT镜像车票
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        if (getValidGptTicket(userIdList).isEmpty()) {
+            throw new BusinessRuntimeException("您没有有效的GPT镜像车票");
+        }
+        //生成标识
+        String code = StringUtil.randomString(6);;
+        GptQuickLinkRecord quickLink = new GptQuickLinkRecord();
+        quickLink.setUserId(userId);
+        quickLink.setCode(code);
+        // 创建新的快捷链接,有效期30天
+        quickLink.setExpiryTime(DateUtil.offsetDay(DateTime.now(), 30));
+        try {
+            gptQuickLinkRecordMapper.insert(quickLink);
+            //将之前的链接变成失效
+            gptQuickLinkRecordMapper.update(null, Wrappers.lambdaUpdate(GptQuickLinkRecord.class)
+                    .set(GptQuickLinkRecord::getExpiryTime, DateTime.now())
+                    .in(GptQuickLinkRecord::getUserId, userIdList)
+                    .ne(GptQuickLinkRecord::getCode, code)
+                    .gt(GptQuickLinkRecord::getExpiryTime, DateTime.now()));
+        } catch (DuplicateKeyException e) {
+            throw BusinessRuntimeException.getInstance("系统繁忙,请重新生成!");
+        }
+        return quickLink;
+    }
+    
+    @Override
+    public GptQuickLinkRecord getLatestQuickLink(Long userId) {
+        Date now = DateTime.now();
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        LambdaQueryWrapper<GptQuickLinkRecord> wrapper = Wrappers.lambdaQuery(GptQuickLinkRecord.class)
+                .in(GptQuickLinkRecord::getUserId, userIdList)
+                .gt(GptQuickLinkRecord::getExpiryTime, now)
+                .orderByDesc(GptQuickLinkRecord::getId)
+                .last("limit 1");
+        return gptQuickLinkRecordMapper.selectOne(wrapper);
+    }
+
+    @Override
+    public GptQuickLinkResp getQuickUrlByCode(String code) {
+        Date now = DateTime.now();
+        LambdaQueryWrapper<GptQuickLinkRecord> wrapper = Wrappers.lambdaQuery(GptQuickLinkRecord.class)
+                .eq(GptQuickLinkRecord::getCode, code)
+                .last("limit 1");
+        GptQuickLinkRecord gptQuickLinkRecord = gptQuickLinkRecordMapper.selectOne(wrapper);
+        if (gptQuickLinkRecord == null) {
+            throw BusinessRuntimeException.getInstance("快捷链接不存在");
+        }
+        GptQuickLinkResp resp = new GptQuickLinkResp();
+        resp.setUserId(gptQuickLinkRecord.getUserId());
+        //成功
+        Integer state = 1;
+        if (gptQuickLinkRecord != null) {
+            if (gptQuickLinkRecord.getExpiryTime().before(now)) {
+                //链接失效
+                state = 2;
+            } else {
+                Long userId = gptQuickLinkRecord.getUserId();
+                List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+                List<GroupsRelationView> validGptTicket = getValidGptTicket(userIdList);
+                if (validGptTicket.isEmpty()) {
+                    //车票过期
+                    state = 3;
+                } else {
+                    if (validGptTicket.size() > 1) {
+                        //多张车票
+                        state = 4;
+                    } else {
+                        GroupsRelationView groupsRelationView = validGptTicket.get(0);
+                        Long relationId = groupsRelationView.getId();
+                        //获取gpt镜像访问url
+                        String url = chatGptAccountService.getCarLoginUrl(getGptDomain(), userId, relationId, Constant.GPT_CARD_ID);
+                        resp.setUrl(url);
+                    }
+                }
+            }
+        }
+        resp.setState(state);
+        return resp;
+    }
+    public List<GroupsRelationView> getValidGptTicket(List<Long> userIdList) {
+        List<GroupsRelationView> relationViews = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
+                .field(GroupsRelationView::getGoodsId, Constant.GPT_PLUS_GID)
+                .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
+                .field(GroupsRelationView::getIsMirror, Boolean.TRUE)
+                .field(GroupsRelationView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
+                .onlySelect(GroupsRelationView::getId)
+                .build());
+        return relationViews;
+    }
+
+    public String getGptDomain() {
+        SysConfig gptNewDomain = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+                .eq(SysConfig::getSysKey, "mirror_gpt_new_domain")
+                .last("limit 1"));
+        if (gptNewDomain != null) {
+            String sysValue = gptNewDomain.getSysValue();
+            if (JSONUtil.isJsonArray(sysValue)) {
+                List<String> domainList = JSONUtil.parseArray(sysValue).toList(String.class);
+                if (CollUtil.isNotEmpty(domainList)) {
+                    int randomInt = RandomUtil.randomInt(domainList.size());
+                    return domainList.get(randomInt);
+                }
+            }
+        }
+        return null;
+    }
+}

+ 75 - 0
netflix-web/src/main/java/com/cyksj/web/controller/api/GptQuickLinkController.java

@@ -0,0 +1,75 @@
+package com.cyksj.web.controller.api;
+
+import cn.hutool.core.util.StrUtil;
+import com.cyksj.common.annotation.NoSubmit;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.GptQuickLinkRecord;
+import com.cyksj.model.response.GptQuickLinkResp;
+import com.cyksj.service.gpt.GptQuickLinkService;
+import com.cyksj.web.util.StpUserUtil;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * GPT快捷链接API控制器
+ */
+@RestController
+@RequestMapping("/applets/gpt/quickLink")
+@RequiredArgsConstructor
+public class GptQuickLinkController {
+    
+    private final GptQuickLinkService gptQuickLinkService;
+    
+    /**
+     * 创建或获取快捷链接
+     */
+    @NoSubmit
+    @PostMapping("/create")
+    public Result<GptQuickLinkResp> createQuickLink() {
+        // 获取当前登录用户ID
+        Long userId = StpUserUtil.getLoginIdAsLong();
+        // 创建或获取快捷链接
+        GptQuickLinkRecord quickLink = gptQuickLinkService.createQuickLink(userId);
+        GptQuickLinkResp resp = new GptQuickLinkResp();
+        resp.setCode(quickLink.getCode());
+        resp.setExpiryTime(quickLink.getExpiryTime());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(resp);
+    }
+    
+    /**
+     * 获取最新的快捷链接
+     */
+    @GetMapping("/get")
+    public Result<GptQuickLinkResp> getLatestQuickLink() {
+        // 获取当前登录用户ID
+        Long userId = StpUserUtil.getLoginIdAsLong();
+        // 获取最新的快捷链接
+        GptQuickLinkRecord quickLink = gptQuickLinkService.getLatestQuickLink(userId);
+        if (quickLink == null) {
+            return GatewayResponse.SUCCESS.newBuilder().toResult();
+        }
+        GptQuickLinkResp resp = new GptQuickLinkResp();
+        resp.setCode(quickLink.getCode());
+        resp.setExpiryTime(quickLink.getExpiryTime());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(resp);
+    }
+
+    /**
+     * 通过快捷链接登录gpt镜像对话页
+     */
+    @GetMapping("/get/chatGpt/page/{code}")
+    public Result<GptQuickLinkResp> getCharGptPageByCode(@PathVariable String code) {
+        GptQuickLinkResp resp = gptQuickLinkService.getQuickUrlByCode(code.trim());
+        if (resp.getState() == 4) {
+            Long userId = resp.getUserId();
+            String token = StpUserUtil.getTokenValueByLoginId(userId);
+            if (StrUtil.isEmpty(token)) {
+                StpUserUtil.login(resp.getUserId());
+                token = StpUserUtil.getTokenValue();
+            }
+            resp.setToken(token);
+        }
+        return GatewayResponse.SUCCESS.newBuilder().toResult(resp);
+    }
+}

+ 70 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java

@@ -13,6 +13,7 @@ import com.alibaba.excel.event.AnalysisEventListener;
 import com.alibaba.excel.support.ExcelTypeEnum;
 import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.annotation.Log;
 import com.cyksj.common.annotation.NoSubmit;
 import com.cyksj.common.constant.Constant;
@@ -44,6 +45,8 @@ import com.cyksj.service.mange.CmsGroupService;
 import com.cyksj.service.mange.cms.CmsUserManager;
 import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.web.util.EasyExcelUtils;
+import com.cyksj.xxljob.XxlJobInfo;
+import com.cyksj.xxljob.XxlJobUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.param.Operator;
@@ -126,6 +129,8 @@ public class CmsAccountController {
 
 	private final DelAccountRecordMapper delAccountRecordMapper;
 
+	private final EnvCommonService envCommonService;
+
 	@GetMapping("/get")
 	@SaCheckPermission("account:view")
 	public Result<SearchResult<AccountView>> get(String title, Long userId, String showId, String nickName, String submitAccount, String expiryStartTime, String expiryEndTime, Boolean expiredAll, Boolean existsExpired, Boolean existsExpiredToday, Integer noChangeMonths, Boolean isMjMirror, String orderNo, Boolean isEmpty) {
@@ -1507,4 +1512,69 @@ public class CmsAccountController {
 		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelBannerNfAccountData.class, list, title, title, ExcelTypeEnum.XLSX, null);
 	}
 
+	/**
+	 * 脆球奈飞账号邮件查询
+	 */
+	@GetMapping("/get/cuiQiu/email/msg")
+	public Result<SearchResult<CuiQiuEmailInfoRecordView>> getCuiQiuEmailMsg(@RequestParam(name = "subjects", required = false) List<String> subjects) {
+		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+		if (CollUtil.isNotEmpty(subjects)) {
+			String cd = " (";
+			for (String subject : subjects) {
+				if (cd.length() > 2) {
+					cd += " or ";
+				}
+				cd += String.format(" cr.subject like '%%%s%%'", subject);
+			}
+			cd += " )";
+			builder.put("sl", cd);
+		}
+		SearchResult<CuiQiuEmailInfoRecordView> search = beanSearcher.search(CuiQiuEmailInfoRecordView.class, builder.orderBy(CuiQiuEmailInfoRecordView::getSendTime).desc().build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 奈飞脆球最新一条数据
+	 */
+	@GetMapping("/get/cuiQiu/email/last")
+	public Result<CuiQiuEmailInfoRecordView> getCuiQiuEmailLast() {
+		CuiQiuEmailInfoRecordView search = beanSearcher.searchFirst(CuiQiuEmailInfoRecordView.class, MapUtils.flatBuilder(request.getParameterMap()).orderBy(CuiQiuEmailInfoRecordView::getSendTime).desc().build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 导出脆球奈飞账号邮件
+	 */
+	@GetMapping("/export/cuiQiu/email/msg")
+	public void export(@RequestParam(name = "subjects", required = false) List<String> subjects, HttpServletResponse response) {
+		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+		if (CollUtil.isNotEmpty(subjects)) {
+			String cd = " (";
+			for (String subject : subjects) {
+				if (cd.length() > 2) {
+					cd += " or ";
+				}
+				cd += String.format(" cr.subject like '%%%s%%'", subject);
+			}
+			cd += " )";
+			builder.put("sl", cd);
+		}
+		List<ExcelCuiQiuEmailInfoRecordData> list = beanSearcher.searchAll(ExcelCuiQiuEmailInfoRecordData.class, builder.orderBy(ExcelCuiQiuEmailInfoRecordData::getSendTime).desc().build());
+		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelCuiQiuEmailInfoRecordData.class, list, "脆球奈飞账号邮件", "脆球奈飞账号邮件", ExcelTypeEnum.XLSX, null);
+	}
+
+	/**
+	 * 同步奈飞脆球最新邮件数据
+	 */
+	@PostMapping("/sync/cuiQiu/nf/last")
+	public Result<String> syncNfCuiQiuLastData() throws Exception {
+		if (envCommonService.isPrdEnv()) {
+			if (!redisService.setNx("nf_cq_email_today_sync", "today", 60 * 5L)) {
+				throw BusinessRuntimeException.getInstance("已开始同步当天最新数据,一般需要5-10分钟,请勿重复点击。");
+			}
+			//立即执行客服值班定时任务
+			XxlJobUtil.executeMarkDynamicRuleTagJob(XxlJobInfo.getExecuteTaskInstance(Constant.NF_CUI_QIU_EMAIL_SYNC_JOB_ID, "today").toString());
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
 }