Merge remote-tracking branch 'origin/master'

This commit is contained in:
Tankaikai
2025-02-21 15:12:01 +08:00
31 changed files with 1594 additions and 1 deletions

View File

@@ -0,0 +1,14 @@
package com.czg.service.account.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.account.entity.CallConfig;
/**
* 叫号配置表 映射层。
*
* @author zs
* @since 2025-02-21
*/
public interface CallConfigMapper extends BaseMapper<CallConfig> {
}

View File

@@ -0,0 +1,19 @@
package com.czg.service.account.mapper;
import com.czg.account.dto.calltable.CallRecordVO;
import com.mybatisflex.core.BaseMapper;
import com.czg.account.entity.CallQueue;
import com.mybatisflex.core.paginate.Page;
/**
* 叫号排号队列表 映射层。
*
* @author zs
* @since 2025-02-21
*/
public interface CallQueueMapper extends BaseMapper<CallQueue> {
Page<CallRecordVO> selectCallRecord();
long selectCallRecord_COUNT();
}

View File

@@ -0,0 +1,14 @@
package com.czg.service.account.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.account.entity.CallTable;
/**
* 叫号桌型表 映射层。
*
* @author zs
* @since 2025-02-21
*/
public interface CallTableMapper extends BaseMapper<CallTable> {
}

View File

@@ -0,0 +1,18 @@
package com.czg.service.account.service.impl;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.account.entity.CallConfig;
import com.czg.account.service.CallConfigService;
import com.czg.service.account.mapper.CallConfigMapper;
import org.springframework.stereotype.Service;
/**
* 叫号配置表 服务层实现。
*
* @author zs
* @since 2025-02-21
*/
@Service
public class CallConfigServiceImpl extends ServiceImpl<CallConfigMapper, CallConfig> implements CallConfigService{
}

View File

@@ -0,0 +1,18 @@
package com.czg.service.account.service.impl;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.account.entity.CallQueue;
import com.czg.account.service.CallQueueService;
import com.czg.service.account.mapper.CallQueueMapper;
import org.springframework.stereotype.Service;
/**
* 叫号排号队列表 服务层实现。
*
* @author zs
* @since 2025-02-21
*/
@Service
public class CallQueueServiceImpl extends ServiceImpl<CallQueueMapper, CallQueue> implements CallQueueService{
}

View File

@@ -0,0 +1,537 @@
package com.czg.service.account.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.czg.account.dto.calltable.*;
import com.czg.account.entity.*;
import com.czg.account.service.*;
import com.czg.config.RedisCst;
import com.czg.exception.ApiNotPrintException;
import com.czg.resp.CzgResult;
import com.czg.service.account.mapper.CallQueueMapper;
import com.czg.service.account.util.FunUtil;
import com.czg.system.dto.SysParamsDTO;
import com.czg.system.service.SysParamsService;
import com.czg.utils.JoinQueryWrapper;
import com.czg.utils.PageUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.service.account.mapper.CallTableMapper;
import jakarta.annotation.Resource;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
* 叫号桌型表 服务层实现。
*
* @author zs
* @since 2025-02-21
*/
@Service
public class CallTableServiceImpl extends ServiceImpl<CallTableMapper, CallTable> implements CallTableService {
// @DubboReference
private SysParamsService sysParamsService;
@Resource
private CallQueueService callQueueService;
@Resource
private ShopUserService shopUserService;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private ShopInfoService shopInfoService;
@Resource
private CallConfigService callConfigService;
@Resource
private CallQueueMapper callQueueMapper;
@Override
public CallTablePage get(Long shopId, Long callTableId, Integer state) {
QueryWrapper query = new QueryWrapper()
.eq(CallTable::getShopId, shopId)
.eq(CallTable::getState, 1);
if (callTableId != null) {
query.eq(CallTable::getId, callTableId);
}
if (state != null) {
query.eq(CallTable::getState, state);
}
Page<CallTable> pageInfo = page(PageUtil.buildPage(), query);
List<CallTable> info = new ArrayList<>();
long totalCount = 0L;
for (CallTable item : pageInfo.getRecords()) {
long count = callQueueService.queryChain()
.eq(CallQueue::getCallTableId, item.getId())
.eq(CallQueue::getShopId, shopId)
.eq(CallQueue::getCreateDay, DateUtil.today())
.in(CallQueue::getState, 0, 1).count();
totalCount += count;
CallTableInfoDTO callTableInfoDTO = BeanUtil.copyProperties(item, CallTableInfoDTO.class);
callTableInfoDTO.setTotalCount(count);
info.add(callTableInfoDTO);
}
CallTablePage callTablePage = BeanUtil.copyProperties(pageInfo, CallTablePage.class);
callTablePage.setRecords(info);
callTablePage.setTotalCount(totalCount);
return callTablePage;
}
@Override
public boolean add(Long shopId, CallTableDTO addCallTableDTO) {
long count = queryChain()
.eq(CallTable::getShopId, shopId)
.and(q -> {
q.eq(CallTable::getName, addCallTableDTO.getName()).or(q1 -> {
q1.eq(CallTable::getPrefix, addCallTableDTO.getPrefix());
});
}).count();
if (count > 0) {
throw new ApiNotPrintException("名称或前缀已存在");
}
CallTable callTable = BeanUtil.copyProperties(addCallTableDTO, CallTable.class);
callTable.setShopId(shopId);
return save(callTable);
}
@Override
public boolean update(Long shopId, UpdateCallTableDTO callTableDTO) {
CallTable callTable = queryChain()
.eq(CallTable::getShopId, shopId)
.eq(CallTable::getId, callTableDTO.getCallTableId()).one();
if (StrUtil.isNotBlank(callTableDTO.getName())) {
long count = queryChain()
.eq(CallTable::getShopId, shopId)
.ne(CallTable::getId, callTableDTO.getCallTableId())
.eq(CallTable::getName, callTableDTO.getName()).count();
if (count > 0) {
throw new ApiNotPrintException("名称已存在");
}
}
if (StrUtil.isNotBlank(callTableDTO.getPrefix())) {
long count = queryChain()
.eq(CallTable::getShopId, shopId)
.ne(CallTable::getId, callTableDTO.getCallTableId())
.eq(CallTable::getPrefix, callTableDTO.getPrefix()).count();
if (count > 0) {
throw new ApiNotPrintException("前缀已存在");
}
}
if (callTable == null) {
throw new ApiNotPrintException("桌型不存在");
}
CallTable newInfo = BeanUtil.copyProperties(callTableDTO, CallTable.class);
newInfo.setId(callTable.getId());
return updateById(newInfo);
}
@Override
public CallTableNumDTO takeNumber(Long shopId, TakeNumberDTO takeNumberDTO) {
ShopInfo shopInfo = shopInfoService.getById(shopId);
CallTable callTable = queryChain()
.eq(CallTable::getShopId, shopId)
.eq(CallTable::getId, takeNumberDTO.getCallTableId()).one();
if (callTable == null) {
throw new ApiNotPrintException("桌型不存在");
}
// 拿取系统内部用户信息
CallQueue callQueue;
if (takeNumberDTO.getUserId() != null) {
ShopUser shopUser = shopUserService.queryChain()
.eq(ShopUser::getStatus, 1)
.eq(ShopUser::getShopId, shopId)
.eq(ShopUser::getId, takeNumberDTO.getUserId()).one();
if (shopUser == null) {
throw new ApiNotPrintException("用户不存在");
}
callQueue = callQueueService.queryChain()
.eq(CallQueue::getUserId, shopUser.getId())
.eq(CallQueue::getShopId, shopId)
.in(CallQueue::getState, 0, 1)
.eq(CallQueue::getCreateDay, DateUtil.today())
.ne(CallQueue::getIsPostpone, 2)
.eq(CallQueue::getCallTableId, takeNumberDTO.getCallTableId()).one();
if (callQueue != null) {
throw new ApiNotPrintException("当前用户已取号");
}
callQueue = BeanUtil.copyProperties(takeNumberDTO, CallQueue.class);
callQueue.setPhone(StrUtil.isBlank(takeNumberDTO.getPhone()) ? shopUser.getPhone() : takeNumberDTO.getPhone());
// callQueue.setOpenId(shopUser.getMiniOpenId());
} else {
// if (StrUtil.isBlank(takeNumberDTO.getPhone()) || StrUtil.isBlank(takeNumberDTO.getOpenId())) {
// throw new ApiNotPrintException("手机号或openId不能为空");
// }
callQueue = callQueueService.queryChain()
.eq(CallQueue::getPhone, takeNumberDTO.getPhone())
.eq(CallQueue::getShopId, shopId)
.eq(CallQueue::getCreateDay, DateUtil.today())
.in(CallQueue::getState, 0, 1)
.ne(CallQueue::getIsPostpone, 2)
.eq(CallQueue::getCallTableId, takeNumberDTO.getCallTableId()).one();
if (callQueue != null) {
throw new ApiNotPrintException("当前用户已取号");
}
callQueue = BeanUtil.copyProperties(takeNumberDTO, CallQueue.class);
callQueue.setPhone(takeNumberDTO.getPhone());
// callQueue.setOpenId(takeNumberDTO.getOpenId());
callQueue.setSubState(0);
}
callQueue.setCreateDay(DateUtil.today());
callQueue.setCallNum(getCallNumber(shopId, callTable));
callQueue.setShopId(shopId);
callQueue.setShopName(shopInfo.getShopName());
callQueueService.save(callQueue);
// todo 打印排号票信息
// rabbitMsgUtils.printCallNumTicket(callQueue.getId(), callQueue.getShopId());
return new CallTableNumDTO().setTableName(callTable.getName()).setTableNote(callTable.getNote())
.setCallNum(callQueue.getCallNum());
}
private String getCallNumber(Long shopId, CallTable callTable) {
return FunUtil.runFunAndCheckKey(() -> {
String callNumKey = RedisCst.getTableCallNumKey(shopId, callTable.getId());
String value = stringRedisTemplate.opsForValue().get(callNumKey);
AtomicReference<String> newVal = new AtomicReference<>("");
// 初始化
if (StrUtil.isBlank(value)) {
Boolean setFlag = FunUtil.runFunAndRetry(() -> stringRedisTemplate.opsForValue().setIfAbsent(callNumKey, callTable.getStart().toString()), flag -> !flag,
_ -> newVal.set(stringRedisTemplate.opsForValue().get(callNumKey)));
if (setFlag) {
return callTable.getPrefix() + callTable.getStart();
} else if (StrUtil.isNotBlank(newVal.get())) {
value = String.valueOf((Integer.parseInt(newVal.get()) + 1));
stringRedisTemplate.opsForValue().set(callNumKey, value);
return callTable.getPrefix() + value;
} else {
throw new ApiNotPrintException("生成排队号码失败");
}
} else {
value = String.valueOf((Integer.parseInt(value) + 1));
stringRedisTemplate.opsForValue().set(callNumKey, value);
return callTable.getPrefix() + value;
}
}, stringRedisTemplate, RedisCst.getLockKey("UPDATE_TABLE", shopId, callTable.getId()));
}
@Override
public String takeNumberCode(Long shopId, Integer callTableId) {
// 创建二维码配置对象设置宽度和高度为400
QrConfig config = new QrConfig(400, 400);
// 使用字节数组输出流来存储二维码图片
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// 生成二维码图片,输出到字节数组输出流
CzgResult<SysParamsDTO> paramsByCode = sysParamsService.getParamsByCode("call_page_url");
if (paramsByCode.getData() == null) {
throw new ApiNotPrintException("页面路径未配置");
}
QrCodeUtil.generate(StrUtil.format(paramsByCode.getData().getParamValue(), shopId, ""), config, "png", outputStream);
// 将图片转换为 Base64 字符串
String base64 = Base64.getEncoder().encodeToString(outputStream.toByteArray());
// 返回Base64格式的图片字符串
return "data:image/png;base64," + base64;
}
@Override
public Integer call(Long shopId, CallQueueDTO callQueueDTO) {
CallQueue callQueue = callQueueService.queryChain()
.notIn(CallQueue::getState, -1, 2)
.eq(CallQueue::getCreateDay, DateUtil.today())
.eq(CallQueue::getId, callQueueDTO.getCallQueueId())
.eq(CallQueue::getShopId, shopId)
.one();
if (callQueue == null) {
throw new ApiNotPrintException("叫号用户不存在");
}
callQueue.setState(1);
callQueue.setCallCount(callQueue.getCallCount() + 1);
callQueueService.updateById(callQueue);
if (callQueue.getSubState().equals(0)) {
return -1;
}
// 发送模板消息通知用户
ShopInfo shopInfo = shopInfoService.getById(shopId);
if (shopInfo == null) {
throw new ApiNotPrintException("店铺信息不存在");
}
List<CallQueue> current = callQueueService.queryChain()
.eq(CallQueue::getCallTableId, callQueue.getCallTableId())
.eq(CallQueue::getCreateDay, DateUtil.today())
.and(r -> {
r.eq(CallQueue::getState, 1)
.or(r1 -> {
r1.eq(CallQueue::getState, 0);
});
})
.orderBy(CallQueue::getCreateTime, true)
.page(new Page<>(1, 1)).getRecords();
if (StrUtil.isBlank(callQueue.getOpenId())) {
return -1;
}
// wxMiniUtils.sendCurrentOrNearCallMsg(shopInfo.getShopName(), getStrByState(Integer.valueOf(callQueue.getState())),
// callQueue.getCallNum(), current.isEmpty() ? "" : current.get(0).getCallNum(), "排号信息", callQueue.getOpenId(), false);
CallConfig config = getConfig(shopId);
// 临近用户提醒
List<CallQueue> nearList = callQueueService.queryChain()
.eq(CallQueue::getCallTableId, callQueue.getCallTableId())
.eq(CallQueue::getCreateDay, DateUtil.today())
.gt(CallQueue::getId, current.getFirst().getId())
.page(new Page<>(config.getNearNum(), 1)).getRecords();
if (!nearList.isEmpty()) {
CallQueue nearQueue = nearList.getFirst();
// wxMiniUtils.sendCurrentOrNearCallMsg(shopInfo.getShopName(), getStrByState(Integer.valueOf(nearQueue.getState())),
// nearQueue.getCallNum(), current.isEmpty() ? "" : current.get(0).getCallNum(), "排号信息", nearQueue.getOpenId(), true);
}
return 1;
}
@Override
public boolean updateInfo(Long shopId, UpdateCallQueueDTO updateCallQueueDTO) {
CallQueue callQueue = callQueueService.queryChain()
.eq(CallQueue::getShopId, shopId)
.eq(CallQueue::getCreateDay, DateUtil.today())
.eq(CallQueue::getId, updateCallQueueDTO.getCallQueueId()).one();
if (callQueue == null) {
throw new ApiNotPrintException("叫号用户不存在");
}
switch (updateCallQueueDTO.getState()) {
case -1:
callQueue.setCancelTime(DateUtil.date().toLocalDateTime());
break;
case 0:
callQueue.setState(0);
break;
case 1:
if (callQueue.getSubState().equals(0)) {
throw new ApiNotPrintException("当前用户未订阅微信提醒");
}
callQueue.setState(1);
callQueue.setCallCount(callQueue.getCallCount() + 1);
callQueue.setCallTime(DateUtil.date().toLocalDateTime());
break;
case 2:
callQueue.setConfirmTime(DateUtil.date().toLocalDateTime());
break;
case 3:
callQueue.setPassTime(DateUtil.date().toLocalDateTime());
// 已经顺延
callQueue.setIsPostpone(callQueue.getIsPostpone() == null ? 1 : callQueue.getIsPostpone() == 0 ? 1 : 2);
ShopInfo shopInfo = shopInfoService.getById(callQueue.getShopId());
if (shopInfo == null) {
throw new ApiNotPrintException("店铺信息不存在");
}
if (StrUtil.isBlank(callQueue.getOpenId()) && callQueue.getSubState() != 1) {
break;
}
CallTable callTable = getById(callQueue.getCallTableId());
Integer isPostpone = callTable.getIsPostpone();
Integer postponeNum = callTable.getPostponeNum();
// 判断是否需要顺延, 暂时注释
if (false && callQueue.getIsPostpone() == 0 && isPostpone != null && isPostpone == 1 && postponeNum != null && postponeNum > 0) {
// 查询当前桌以及顺延桌数
List<CallQueue> current = callQueueService.queryChain()
.eq(CallQueue::getCallTableId, callQueue.getCallTableId())
.eq(CallQueue::getCreateDay, DateUtil.today())
.eq(CallQueue::getShopId, callTable.getShopId())
.ge(CallQueue::getId, callQueue.getId())
.orderBy(CallQueue::getCreateTime, true)
.page(new Page<>(1, postponeNum + 1)) // 获取当前桌和顺延的桌数
.getRecords();
// 确保有足够的桌可以顺延
if (current.size() > 1) {
// 获取当前桌以及顺延桌
CallQueue currentTable = BeanUtil.copyProperties(current.getFirst(), CallQueue.class);
// 顺延替换信息,将每一张顺延桌向前移动
for (int i = 0; i < current.size() - 1; i++) {
exchangeCallQueueInfo(current.get(i), current.get(i + 1)); // 当前桌替换为顺延桌
}
exchangeCallQueueInfo(current.getLast(), currentTable);
callQueue = current.getLast();
// 更新数据库中的桌号信息
callQueueService.updateBatch(current);
}
}
List<CallQueue> current = callQueueService.queryChain()
.eq(CallQueue::getCallTableId, callQueue.getCallTableId())
.eq(CallQueue::getCreateDay, DateUtil.today())
.and(r -> {
r.eq(CallQueue::getState, 1)
.or(q -> {
q.eq(CallQueue::getState, 0);
});
})
.orderBy(CallQueue::getCreateTime, true)
.page(new Page<>(1, 1)).getRecords();
// wxMiniUtils.sendPassCallMsg(shopInfo.getShopName(), getStrByState(Integer.valueOf(updateCallQueueDTO.getState())),
// callQueue.getCallNum(), current.isEmpty() ? "" : current.get(0).getCallNum(), "即将过号", callQueue.getOpenId());
break;
default:
throw new ApiNotPrintException("错误类型");
}
callQueue.setState(updateCallQueueDTO.getState());
return callQueueService.updateById(callQueue);
}
private void exchangeCallQueueInfo(CallQueue setCallQueue, CallQueue copyCallQueue) {
setCallQueue.setOpenId(copyCallQueue.getOpenId());
setCallQueue.setState(copyCallQueue.getState());
setCallQueue.setSubState(copyCallQueue.getSubState());
setCallQueue.setCreateTime(copyCallQueue.getCreateTime());
setCallQueue.setName(copyCallQueue.getName());
setCallQueue.setNote(copyCallQueue.getNote());
setCallQueue.setCallNum(copyCallQueue.getCallNum());
setCallQueue.setCallTime(copyCallQueue.getCallTime());
setCallQueue.setCallCount(copyCallQueue.getCallCount());
setCallQueue.setPassTime(copyCallQueue.getPassTime());
setCallQueue.setCancelTime(copyCallQueue.getCancelTime());
setCallQueue.setUserId(copyCallQueue.getUserId());
setCallQueue.setConfirmTime(copyCallQueue.getConfirmTime());
}
@Override
public Page<CallQueue> getQueue(Long shopId, Long callTableId, Integer state) {
List<Long> tableIds;
if (callTableId != null) {
tableIds = Collections.singletonList(callTableId);
} else {
List<CallTable> list = queryChain().eq(CallTable::getShopId, shopId).eq(CallTable::getState, 1).list();
if (list.isEmpty()) {
return new Page<>();
}
tableIds = list.stream()
.map(CallTable::getId)
.collect(Collectors.toList());
}
QueryWrapper query = callQueueService.queryChain()
.eq(CallQueue::getShopId, shopId)
.eq(CallQueue::getCreateDay, DateUtil.today())
.in(CallQueue::getCallTableId, tableIds);
if (state != null) {
query.eq(CallQueue::getState, state);
} else {
query.in(CallQueue::getState, 0, 1);
}
Page<CallQueue> pageInfo = callQueueService.page(PageUtil.buildPage(), query
.orderBy(CallQueue::getCreateTime, true)
.orderBy(CallQueue::getState, false));
List<CallQueue> list1 = pageInfo.getRecords();
// 创建返回的结果集
List<CallQueue> resultList = new ArrayList<>();
// 遍历每一个叫号中的记录,计算前面状态为"0" (排队中) 的人数
for (CallQueue calling : list1) {
// 计算前面等待的人数 (状态为"0"且在叫号记录创建时间之前的)
long waitingCount = 0;
if (calling.getState() == 0) {
waitingCount = list1.stream()
.filter(item -> item.getState() == 0 || item.getState() == 1) // 过滤出状态为"排队中"的
.filter(item -> item.getCreateTime().isBefore(calling.getCreateTime())) // 时间在当前叫号之前
.count();
}
// 创建一个Map来保存叫号中的记录及其前面排队的人数
CallQueueListDTO callQueueListDTO = BeanUtil.copyProperties(calling, CallQueueListDTO.class);
callQueueListDTO.setWaitingCount(waitingCount);
// 将该map加入结果集
resultList.add(callQueueListDTO);
}
pageInfo.setRecords(resultList);
// 返回结果列表
return pageInfo;
}
@Override
public Page<CallRecordVO> getCallRecord(Long shopId, Integer callTableId) {
QueryWrapper queryWrapper = new JoinQueryWrapper().eq(CallQueue::getShopId, shopId).in(CallQueue::getState, 3, 2, 1).orderBy(CallQueue::getCreateTime, false);
if (callTableId != null) {
queryWrapper.eq(CallQueue::getCallTableId, callTableId);
}
return callQueueMapper.xmlPaginate("selectCallRecord", PageUtil.buildPage(), queryWrapper);
}
@Override
public CallConfig getConfig(Long shopId) {
CallConfig config = callConfigService.queryChain().eq(CallConfig::getShopId, shopId).one();
if (config == null) {
config = new CallConfig();
config.setShopId(shopId);
callConfigService.save(config);
config = callConfigService.queryChain().eq(CallConfig::getShopId, shopId).one();
}
return config;
}
@Override
public boolean updateConfig(Long shopId, UpdateConfigDTO configDTO) {
CallConfig config = callConfigService.queryChain().eq(CallConfig::getShopId, shopId).one();
if (config == null) {
throw new ApiNotPrintException("未查询到配置信息");
}
CallConfig tbCallConfig = BeanUtil.copyProperties(configDTO, CallConfig.class);
tbCallConfig.setId(config.getId());
return callConfigService.updateById(tbCallConfig);
}
}

View File

@@ -65,7 +65,7 @@ public class ShopUserServiceImpl extends ServiceImpl<ShopUserMapper, ShopUser> i
});
});
// queryWrapper.and(JoinQueryWrapper.column(UserInfo::getNickName).like(key).or(JoinQueryWrapper.column(UserInfo::getPhone).like(key)));
queryWrapper.and(column(UserInfo::getNickName).like(key).or(column(UserInfo::getPhone).like(key)));
}
if (isVip != null) {

View File

@@ -0,0 +1,64 @@
package com.czg.service.account.util;
import com.czg.exception.ApiNotPrintException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* @author Administrator
*/
@Slf4j
public class FunUtil {
public static int retryCount = 5;
public static<T> T runFunAndCheckKey(Supplier<T> supplier, StringRedisTemplate redisTemplate, String lockKey) {
try{
// 设置分布式锁
boolean lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 30, TimeUnit.MILLISECONDS));
int count = 0;
while (!lock) {
if (count++ > 100) {
throw new ApiNotPrintException("系统繁忙, 稍后再试");
}
Thread.sleep(20);
lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 30, TimeUnit.MILLISECONDS));
}
return supplier.get();
} catch (RuntimeException e){
log.info("执行出错:{}", e.getMessage());
throw e;
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally{
redisTemplate.delete(lockKey);
}
}
public static <T, R> R runFunAndRetry(
Supplier<R> function,
Function<R, Boolean> check, Consumer<R> errFun) {
log.info("工具类开始执行函数");
R result = function.get();
boolean flag = check.apply(result);
log.info("执行结果: {}", result);
while (flag && retryCount-- > 0) {
log.info("执行函数失败, 剩余尝试次数{}", retryCount);
result = function.get();
log.info("执行结果: {}", result);
flag = check.apply(result);
}
if (flag) {
errFun.accept(result);
}
return result;
}
}

View File

@@ -0,0 +1,7 @@
<?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.czg.service.account.mapper.CallConfigMapper">
</mapper>

View File

@@ -0,0 +1,20 @@
<?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.czg.service.account.mapper.CallQueueMapper">
<select id="selectCallRecord" resultType="com.czg.account.dto.calltable.CallRecordVO">
select tb_call_queue.*, tb_call_table.note, TIMESTAMPDIFF(SECOND, tb_call_queue.create_time, NOW()) as since_at
from tb_call_queue
left join tb_call_table on tb_call_queue.call_table_id = tb_call_table.id
${qwSql}
limit ${pageOffset}, ${pageSize}
</select>
<select id="selectCallRecord_COUNT" resultType="java.lang.Long">
select count(1)
from tb_call_queue
left join tb_call_table on tb_call_queue.call_table_id = tb_call_table.id
${qwSql}
</select>
</mapper>

View File

@@ -0,0 +1,7 @@
<?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.czg.service.account.mapper.CallTableMapper">
</mapper>