package com.cyksj.web.controller.sys; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.cyksj.common.annotation.Log; import com.cyksj.common.constant.Constant; import com.cyksj.common.exception.BusinessRuntimeException; import com.cyksj.common.util.Jsons; import com.cyksj.dto.RedisKey; import com.cyksj.dto.Result; import com.cyksj.enums.BusinessType; import com.cyksj.enums.GatewayResponse; import com.cyksj.mapper.manage.cps.CpsUserAdRecordMapper; import com.cyksj.mapper.manage.help.HelpQuestionClassificationMapper; import com.cyksj.mapper.manage.help.HelpQuestionMapper; import com.cyksj.model.dto.EquipmentConfigDto; import com.cyksj.model.dto.SysServiceChangeDto; import com.cyksj.model.entity.HelpQuestion; import com.cyksj.model.entity.HelpQuestionClassification; import com.cyksj.model.entity.SysConfig; import com.cyksj.model.entity.SysConfigChangeRecord; import com.cyksj.model.views.HelpQuestionClassificationView; import com.cyksj.redis.RedisService; import com.cyksj.service.corp.CorpCustomerAcquisitionLinkService; import com.cyksj.service.sys.SysConfigChangeRecordService; import com.cyksj.service.sys.SysConfigService; import com.cyksj.web.util.StpUserUtil; 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; import com.ejlchina.searcher.util.MapUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.util.HashSet; /** admin/客服运营 * @author chan * @date 2022/10/20 10:08 AM */ @Slf4j @RequestMapping("/sys") @RestController @RequiredArgsConstructor public class SysConfigController { private final SysConfigService sysConfigService; private final HelpQuestionMapper helpQuestionMapper; private final HelpQuestionClassificationMapper helpQuestionClassificationMapper; private final BeanSearcher beanSearcher; private final HttpServletRequest request; private final RedisService redisService; private final SysConfigChangeRecordService sysConfigChangeRecordService; private final CpsUserAdRecordMapper cpsUserAdRecordMapper; private final CorpCustomerAcquisitionLinkService corpCustomerAcquisitionLinkService; @GetMapping("/get") public Result get(String key) { try { String cacheKey = RedisService.key.SYS_CONFIG_CACHE_KEY.getName() + key; Object o = redisService.get(cacheKey); if (o != null) { return GatewayResponse.SUCCESS.newBuilder().toResult((SysConfig) o); } // 加锁防止缓存击穿 String lockKey = cacheKey + ":lock"; if (redisService.setNx(lockKey, "1", 10L)) { try { o = redisService.get(cacheKey); if (o != null) { return GatewayResponse.SUCCESS.newBuilder().toResult((SysConfig) o); } SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, key).last(" limit 1")); if (sysConfig == null) { throw new BusinessRuntimeException("配置不存在"); } redisService.set(cacheKey, sysConfig, RedisService.key.SYS_CONFIG_CACHE_KEY.getTimeout()); return GatewayResponse.SUCCESS.newBuilder().toResult(sysConfig); } finally { redisService.del(lockKey); } } else { // 未获取锁,返回空 throw new BusinessRuntimeException("配置不存在"); } } catch (BusinessRuntimeException e) { throw e; } catch (Exception e) { // Redis异常,返回空保护数据库 throw new BusinessRuntimeException("配置不存在"); } } @PostMapping("/post") @Log(module = "系统设置/新增配置", businessType = BusinessType.POST, isSaveRequestData = true) public Result post(@RequestBody SysConfig sysConfig) { sysConfigService.save(sysConfig); return GatewayResponse.SUCCESS.newBuilder().toResult(sysConfig); } @PutMapping("/update") @Log(module = "系统设置/编辑配置", businessType = BusinessType.PUT, isSaveRequestData = true) public Result update(@RequestBody SysConfig sysConfig) throws Exception { long adminId = StpUtil.getLoginIdAsLong(); Long id = sysConfig.getId(); SysConfig byId = sysConfigService.getById(id); sysConfig.setSysKey(byId.getSysKey()); if (Constant.EQUIPMENT_DISTRIBUTE_KEY.equals(sysConfig.getSysKey())) { String sysValue = sysConfig.getSysValue(); if (StrUtil.isNotBlank(sysValue)) { EquipmentConfigDto equipmentConfigDto = Jsons.parseObject(sysValue, EquipmentConfigDto.class); if (CollUtil.isNotEmpty(equipmentConfigDto.getSkuList())) { equipmentConfigDto.setBalance(BigDecimal.ZERO); } if (equipmentConfigDto.getBalance() != null && equipmentConfigDto.getBalance().compareTo(BigDecimal.ZERO) > 0) { equipmentConfigDto.setSkuList(new HashSet<>()); } sysConfig.setSysValue(Jsons.toJson(equipmentConfigDto)); } } SysServiceChangeDto changeRecord = sysConfigChangeRecordService.changeRecord(adminId, sysConfig.getSysKey(), byId.getSysValue(), sysConfig.getSysValue()); sysConfigService.updateById(sysConfig); //同步获客值班客服 if (Constant.serviceKeys.get(0).equals(sysConfig.getSysKey())) { corpCustomerAcquisitionLinkService.syncDutyLinkUrl(); } if (changeRecord.getChangeCsImg()) { //立即执行客服值班定时任务 XxlJobUtil.executeMarkDynamicRuleTagJob(XxlJobInfo.getExecuteTaskInstance(Constant.CORP_LINK_JOB_ID, StrUtil.EMPTY).toString()); } if (changeRecord.getChangeCsName()) { sysConfigChangeRecordService.updateCorpFollowLinkConfig(changeRecord.getUpdateFollowIndxs()); } String key = sysConfig.getSysKey(); String cacheKey = RedisService.key.SYS_CONFIG_CACHE_KEY.getName() + key; if (redisService.hasKey(cacheKey)) { redisService.set(cacheKey, sysConfig, RedisService.key.SYS_CONFIG_CACHE_KEY.getTimeout()); } return GatewayResponse.SUCCESS.newBuilder().toResult(sysConfig); } @DeleteMapping("/delete/{id}") @Log(module = "系统设置/删除配置", businessType = BusinessType.DELETE) public Result update(@PathVariable Long id) { SysConfig byId = sysConfigService.getById(id); if (byId != null) { sysConfigService.removeById(id); String key = byId.getSysKey(); String cacheKey = RedisService.key.SYS_CONFIG_CACHE_KEY.getName() + key; if (redisService.hasKey(cacheKey)) { redisService.del(cacheKey); } } return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 问题分类列表 */ @GetMapping("/help/question/classification/get") public Result> get(Long goodsId, @RequestParam(defaultValue = "1") Integer start, @RequestParam(defaultValue = "5") Integer limit) { Page page = helpQuestionClassificationMapper.getQuestionClassificationView(goodsId, new Page<>(start, limit)); page.getRecords().forEach(data -> { data.setQuestions(helpQuestionMapper.selectList(Wrappers.lambdaQuery(HelpQuestion.class) .eq(HelpQuestion::getClassificationId, data.getId()) .eq(HelpQuestion::getDeleted, true) .eq(HelpQuestion::getStatus, true) .orderByDesc(HelpQuestion::getSort))); }); return GatewayResponse.SUCCESS.newBuilder().toResult(page); } /** * 问题详情 */ @GetMapping("/get/question/detail") public Result getQuestionById(Long id) { if (id == null || id < 1) { throw BusinessRuntimeException.getInstance("id error"); } HelpQuestion helpQuestion = helpQuestionMapper.selectById(id); return GatewayResponse.SUCCESS.newBuilder().toResult(helpQuestion); } /** * 平台是否有关联上架的问题分类 */ @GetMapping("/check/goods/question/classification") public Result checkGoodsQuestionClassification(Long goodsId) { if (goodsId == null || goodsId < 0) { throw BusinessRuntimeException.getInstance("id error"); } HelpQuestionClassification helpQuestionClassification = helpQuestionClassificationMapper.selectOne(Wrappers.lambdaQuery(HelpQuestionClassification.class) .eq(HelpQuestionClassification::getGoodsId, goodsId) .eq(HelpQuestionClassification::getDeleted, true) .eq(HelpQuestionClassification::getStatus, true) .last("limit 1")); return GatewayResponse.SUCCESS.newBuilder().toResult(helpQuestionClassification != null ? true : false); } /** * 值班客服操作日志 */ @GetMapping("/duty/operate/log") public Result> sysConfigChangeRecordResult() { SearchResult search = beanSearcher.search(SysConfigChangeRecord.class, MapUtils.flatBuilder(request.getParameterMap()) .field(SysConfigChangeRecord::getChangeStr).op(Operator.NotNull) .orderBy(SysConfigChangeRecord::getId).desc() .onlySelect(SysConfigChangeRecord::getId, SysConfigChangeRecord::getOperator, SysConfigChangeRecord::getChangeStr, SysConfigChangeRecord::getCreatedTime) .build()); return GatewayResponse.SUCCESS.newBuilder().toResult(search); } /** * 当前用户是否获取了客服 */ @GetMapping("/get/service/indx") public Result getServiceIndx() { long userId = StpUserUtil.getLoginIdAsLong(); long time = DateUtil.beginOfDay(DateTime.now()).getTime(); Object re = redisService.get(RedisService.key.EQUIPMENT_USER_SERVICE_RECORD.getName() + time + userId); return GatewayResponse.SUCCESS.newBuilder().toResult(re); } /** * 记录用户获取的客服 */ @PostMapping("/service/record/{indx}") public Result serviceRecord(@PathVariable Long indx) { long userId = StpUserUtil.getLoginIdAsLong(); long time = DateUtil.beginOfDay(DateTime.now()).getTime(); redisService.set(RedisService.key.EQUIPMENT_USER_SERVICE_RECORD.getName() + time + userId, indx, RedisService.key.EQUIPMENT_USER_SERVICE_RECORD.getTimeout()); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 清零用户获取广告记录 */ @DeleteMapping("/delete/cps/ad") public Result deleteCpsAdRecord() { cpsUserAdRecordMapper.delete(null); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 获取客服下标 */ @GetMapping("/get/service/index") public Result getCorpFollowIndex(@RequestParam(defaultValue = "1") Integer type) { //客服下表类型 String oriType = type == 1 ? "ep" : "other"; String key = RedisKey.SERVICE_INDEX_KEY + oriType; Long index = redisService.incr(key, 1l); if (index == 10) { redisService.set(key, 0); } return GatewayResponse.SUCCESS.newBuilder().toResult(index - 1); } }