|
@@ -0,0 +1,370 @@
|
|
|
|
|
+package shop.alien.store.service.impl;
|
|
|
|
|
+
|
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
+import shop.alien.entity.store.StoreTable;
|
|
|
|
|
+import shop.alien.entity.store.StoreTableLog;
|
|
|
|
|
+import shop.alien.entity.store.dto.StoreTableChangeDTO;
|
|
|
|
|
+import shop.alien.entity.store.dto.StoreTableDTO;
|
|
|
|
|
+import shop.alien.entity.store.vo.StoreTableStatusVO;
|
|
|
|
|
+import shop.alien.mapper.StoreTableLogMapper;
|
|
|
|
|
+import shop.alien.mapper.StoreTableMapper;
|
|
|
|
|
+import shop.alien.store.config.BaseRedisService;
|
|
|
|
|
+import shop.alien.store.service.StoreTableService;
|
|
|
|
|
+import shop.alien.store.service.WeChatMiniProgramQrCodeService;
|
|
|
|
|
+import shop.alien.util.common.JwtUtil;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.Collections;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 桌号表 服务实现类
|
|
|
|
|
+ *
|
|
|
|
|
+ * @author system
|
|
|
|
|
+ * @since 2025-01-XX
|
|
|
|
|
+ */
|
|
|
|
|
+@Slf4j
|
|
|
|
|
+@Service
|
|
|
|
|
+@Transactional
|
|
|
|
|
+@RequiredArgsConstructor
|
|
|
|
|
+public class StoreTableServiceImpl extends ServiceImpl<StoreTableMapper, StoreTable> implements StoreTableService {
|
|
|
|
|
+
|
|
|
|
|
+ private final StoreTableLogMapper storeTableLogMapper;
|
|
|
|
|
+ private final WeChatMiniProgramQrCodeService weChatMiniProgramQrCodeService;
|
|
|
|
|
+ private final BaseRedisService baseRedisService;
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public IPage<StoreTable> getTablePage(Integer pageNum, Integer pageSize, Integer storeId, Integer status) {
|
|
|
|
|
+ log.info("StoreTableServiceImpl.getTablePage?pageNum={}&pageSize={}&storeId={}&status={}", pageNum, pageSize, storeId, status);
|
|
|
|
|
+ LambdaQueryWrapper<StoreTable> wrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ wrapper.eq(StoreTable::getStoreId, storeId)
|
|
|
|
|
+ .eq(status != null, StoreTable::getStatus, status)
|
|
|
|
|
+ .orderByAsc(StoreTable::getTableNumber);
|
|
|
|
|
+ return this.page(new Page<>(pageNum, pageSize), wrapper);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean batchCreateTables(Integer storeId, List<String> tableNumbers) {
|
|
|
|
|
+ log.info("StoreTableServiceImpl.batchCreateTables?storeId={}&tableNumbers={}", storeId, tableNumbers);
|
|
|
|
|
+
|
|
|
|
|
+ // 从JWT获取当前登录用户ID
|
|
|
|
|
+ Integer userId = getCurrentUserId();
|
|
|
|
|
+
|
|
|
|
|
+ if (storeId == null || tableNumbers == null || tableNumbers.isEmpty()) {
|
|
|
|
|
+ log.warn("批量创建桌号失败:参数不完整");
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查桌号是否已存在
|
|
|
|
|
+ LambdaQueryWrapper<StoreTable> checkWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ checkWrapper.eq(StoreTable::getStoreId, storeId)
|
|
|
|
|
+ .in(StoreTable::getTableNumber, tableNumbers);
|
|
|
|
|
+ List<StoreTable> existingTables = this.list(checkWrapper);
|
|
|
|
|
+
|
|
|
|
|
+ if (!existingTables.isEmpty()) {
|
|
|
|
|
+ List<String> existingNumbers = existingTables.stream()
|
|
|
|
|
+ .map(StoreTable::getTableNumber)
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ log.warn("批量创建桌号失败:桌号已存在,{}", existingNumbers);
|
|
|
|
|
+ throw new RuntimeException("桌号已存在:" + String.join(",", existingNumbers));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 批量创建
|
|
|
|
|
+ List<StoreTable> tables = tableNumbers.stream()
|
|
|
|
|
+ .map(tableNumber -> {
|
|
|
|
|
+ StoreTable table = new StoreTable();
|
|
|
|
|
+ table.setStoreId(storeId);
|
|
|
|
|
+ table.setTableNumber(tableNumber);
|
|
|
|
|
+ table.setStatus(0); // 默认空闲
|
|
|
|
|
+ table.setCreatedUserId(userId);
|
|
|
|
|
+ return table;
|
|
|
|
|
+ })
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = this.saveBatch(tables);
|
|
|
|
|
+
|
|
|
|
|
+ // 批量创建成功后,异步生成小程序二维码
|
|
|
|
|
+ if (result) {
|
|
|
|
|
+ asyncGenerateQrCodesForTables(storeId, tableNumbers);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 异步为新创建的桌号生成二维码
|
|
|
|
|
+ */
|
|
|
|
|
+ @Async
|
|
|
|
|
+ public void asyncGenerateQrCodesForTables(Integer storeId, List<String> tableNumbers) {
|
|
|
|
|
+ log.info("开始异步生成桌号二维码, storeId={}, tableNumbers={}", storeId, tableNumbers);
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 查询刚创建的桌号
|
|
|
|
|
+ LambdaQueryWrapper<StoreTable> wrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ wrapper.eq(StoreTable::getStoreId, storeId)
|
|
|
|
|
+ .in(StoreTable::getTableNumber, tableNumbers)
|
|
|
|
|
+ .isNull(StoreTable::getQrcodeUrl);
|
|
|
|
|
+ List<StoreTable> tables = this.list(wrapper);
|
|
|
|
|
+
|
|
|
|
|
+ for (StoreTable table : tables) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ String qrCodeUrl = weChatMiniProgramQrCodeService.generateTableQrCode(table.getId(), storeId);
|
|
|
|
|
+ if (qrCodeUrl != null && !qrCodeUrl.isEmpty()) {
|
|
|
|
|
+ // 更新二维码URL
|
|
|
|
|
+ LambdaUpdateWrapper<StoreTable> updateWrapper = new LambdaUpdateWrapper<>();
|
|
|
|
|
+ updateWrapper.eq(StoreTable::getId, table.getId())
|
|
|
|
|
+ .set(StoreTable::getQrcodeUrl, qrCodeUrl);
|
|
|
|
|
+ this.update(updateWrapper);
|
|
|
|
|
+ log.info("桌号二维码生成成功, tableId={}, qrCodeUrl={}", table.getId(), qrCodeUrl);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("生成桌号二维码失败, tableId={}, error={}", table.getId(), e.getMessage(), e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("异步生成桌号二维码完成, storeId={}, count={}", storeId, tables.size());
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("异步生成桌号二维码异常, storeId={}, error={}", storeId, e.getMessage(), e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean updateTable(StoreTableDTO dto) {
|
|
|
|
|
+ log.info("StoreTableServiceImpl.updateTable?dto={}", dto);
|
|
|
|
|
+
|
|
|
|
|
+ StoreTable table = this.getById(dto.getId());
|
|
|
|
|
+ if (table == null) {
|
|
|
|
|
+ log.warn("更新桌号失败:桌号不存在,id={}", dto.getId());
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果修改了桌号,检查新桌号是否已存在
|
|
|
|
|
+ if (!dto.getTableNumber().equals(table.getTableNumber())) {
|
|
|
|
|
+ LambdaQueryWrapper<StoreTable> wrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ wrapper.eq(StoreTable::getStoreId, table.getStoreId())
|
|
|
|
|
+ .eq(StoreTable::getTableNumber, dto.getTableNumber())
|
|
|
|
|
+ .ne(StoreTable::getId, dto.getId());
|
|
|
|
|
+ StoreTable existingTable = this.getOne(wrapper);
|
|
|
|
|
+ if (existingTable != null) {
|
|
|
|
|
+ log.warn("更新桌号失败:桌号已存在,tableNumber={}", dto.getTableNumber());
|
|
|
|
|
+ throw new RuntimeException("桌号已存在:" + dto.getTableNumber());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 从JWT获取当前登录用户ID
|
|
|
|
|
+ Integer userId = getCurrentUserId();
|
|
|
|
|
+
|
|
|
|
|
+ LambdaUpdateWrapper<StoreTable> updateWrapper = new LambdaUpdateWrapper<>();
|
|
|
|
|
+ updateWrapper.eq(StoreTable::getId, dto.getId())
|
|
|
|
|
+ .set(StoreTable::getTableNumber, dto.getTableNumber());
|
|
|
|
|
+ if (userId != null) {
|
|
|
|
|
+ updateWrapper.set(StoreTable::getUpdatedUserId, userId);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = this.update(updateWrapper);
|
|
|
|
|
+
|
|
|
|
|
+ // 更新成功后,异步更新小程序二维码
|
|
|
|
|
+ if (result) {
|
|
|
|
|
+ asyncUpdateQrCodeForTable(dto.getId(), table.getStoreId());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 异步更新桌号的小程序二维码
|
|
|
|
|
+ */
|
|
|
|
|
+ @Async
|
|
|
|
|
+ public void asyncUpdateQrCodeForTable(Integer tableId, Integer storeId) {
|
|
|
|
|
+ log.info("开始异步更新桌号二维码, tableId={}, storeId={}", tableId, storeId);
|
|
|
|
|
+ try {
|
|
|
|
|
+ String qrCodeUrl = weChatMiniProgramQrCodeService.generateTableQrCode(tableId, storeId);
|
|
|
|
|
+ if (qrCodeUrl != null && !qrCodeUrl.isEmpty()) {
|
|
|
|
|
+ // 更新二维码URL
|
|
|
|
|
+ LambdaUpdateWrapper<StoreTable> updateWrapper = new LambdaUpdateWrapper<>();
|
|
|
|
|
+ updateWrapper.eq(StoreTable::getId, tableId)
|
|
|
|
|
+ .set(StoreTable::getQrcodeUrl, qrCodeUrl);
|
|
|
|
|
+ this.update(updateWrapper);
|
|
|
|
|
+ log.info("桌号二维码更新成功, tableId={}, qrCodeUrl={}", tableId, qrCodeUrl);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("更新桌号二维码失败, tableId={}, error={}", tableId, e.getMessage(), e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean deleteTable(Integer id) {
|
|
|
|
|
+ log.info("StoreTableServiceImpl.deleteTable?id={}", id);
|
|
|
|
|
+
|
|
|
|
|
+ StoreTable table = this.getById(id);
|
|
|
|
|
+ if (table == null) {
|
|
|
|
|
+ log.warn("删除桌号失败:桌号不存在,id={}", id);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果桌号正在使用中,不允许删除
|
|
|
|
|
+ if (table.getStatus() != null && table.getStatus() == 1) {
|
|
|
|
|
+ log.warn("删除桌号失败:桌号正在使用中,id={}", id);
|
|
|
|
|
+ throw new RuntimeException("桌号正在使用中,无法删除");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return this.removeById(id);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean changeTable(StoreTableChangeDTO dto) {
|
|
|
|
|
+ log.info("StoreTableServiceImpl.changeTable?dto={}", dto);
|
|
|
|
|
+
|
|
|
|
|
+ // 查询原桌号
|
|
|
|
|
+ StoreTable fromTable = this.getById(dto.getFromTableId());
|
|
|
|
|
+ if (fromTable == null) {
|
|
|
|
|
+ log.warn("换桌失败:原桌号不存在,fromTableId={}", dto.getFromTableId());
|
|
|
|
|
+ throw new RuntimeException("原桌号不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查原桌号的订单ID是否匹配
|
|
|
|
|
+ if (fromTable.getCurrentOrderId() == null || !fromTable.getCurrentOrderId().equals(dto.getOrderId())) {
|
|
|
|
|
+ log.warn("换桌失败:原桌号的订单ID不匹配,fromTableId={}, currentOrderId={}, orderId={}",
|
|
|
|
|
+ dto.getFromTableId(), fromTable.getCurrentOrderId(), dto.getOrderId());
|
|
|
|
|
+ throw new RuntimeException("原桌号的订单ID不匹配");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查门店ID是否一致(先检查,避免后续不必要的操作)
|
|
|
|
|
+ if (dto.getFromTableId().equals(dto.getToTableId())) {
|
|
|
|
|
+ log.warn("换桌失败:原桌号和目标桌号不能相同");
|
|
|
|
|
+ throw new RuntimeException("原桌号和目标桌号不能相同");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 使用分布式锁锁定目标桌号,防止并发冲突
|
|
|
|
|
+ String lockKey = "table:change:" + dto.getToTableId();
|
|
|
|
|
+ String lockIdentifier = baseRedisService.lock(lockKey, 10000, 5000); // 锁10秒,获取锁超时5秒
|
|
|
|
|
+
|
|
|
|
|
+ if (lockIdentifier == null) {
|
|
|
|
|
+ log.warn("换桌失败:获取目标桌号锁失败,可能正在被其他操作占用,toTableId={}", dto.getToTableId());
|
|
|
|
|
+ throw new RuntimeException("目标桌号正在被占用,请稍后重试");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 重新查询目标桌号(在锁内查询,确保获取最新状态)
|
|
|
|
|
+ StoreTable toTable = this.getById(dto.getToTableId());
|
|
|
|
|
+ if (toTable == null) {
|
|
|
|
|
+ log.warn("换桌失败:目标桌号不存在,toTableId={}", dto.getToTableId());
|
|
|
|
|
+ throw new RuntimeException("目标桌号不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查门店ID是否一致
|
|
|
|
|
+ if (!fromTable.getStoreId().equals(toTable.getStoreId())) {
|
|
|
|
|
+ log.warn("换桌失败:桌号不在同一门店,fromTableId={}, toTableId={}", dto.getFromTableId(), dto.getToTableId());
|
|
|
|
|
+ throw new RuntimeException("桌号不在同一门店");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 从JWT获取当前登录用户ID
|
|
|
|
|
+ Integer userId = getCurrentUserId();
|
|
|
|
|
+
|
|
|
|
|
+ // 更新原桌号:状态为空闲,清空订单ID
|
|
|
|
|
+ LambdaUpdateWrapper<StoreTable> fromUpdateWrapper = new LambdaUpdateWrapper<>();
|
|
|
|
|
+ fromUpdateWrapper.eq(StoreTable::getId, dto.getFromTableId())
|
|
|
|
|
+ .eq(StoreTable::getCurrentOrderId, dto.getOrderId()) // 确保订单ID匹配
|
|
|
|
|
+ .set(StoreTable::getStatus, 0)
|
|
|
|
|
+ .set(StoreTable::getCurrentOrderId, null);
|
|
|
|
|
+ boolean fromUpdateResult = this.update(fromUpdateWrapper);
|
|
|
|
|
+
|
|
|
|
|
+ if (!fromUpdateResult) {
|
|
|
|
|
+ log.warn("换桌失败:更新原桌号失败,可能订单状态已变化,fromTableId={}, orderId={}",
|
|
|
|
|
+ dto.getFromTableId(), dto.getOrderId());
|
|
|
|
|
+ throw new RuntimeException("原桌号的订单状态已变化,请刷新后重试");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 使用条件更新目标桌号:只有在空闲状态且无订单时才能更新
|
|
|
|
|
+ // 这样可以确保即使有其他用户扫码,也能保证原子性
|
|
|
|
|
+ LambdaUpdateWrapper<StoreTable> toUpdateWrapper = new LambdaUpdateWrapper<>();
|
|
|
|
|
+ toUpdateWrapper.eq(StoreTable::getId, dto.getToTableId())
|
|
|
|
|
+ .eq(StoreTable::getStatus, 0) // 必须是空闲状态
|
|
|
|
|
+ .isNull(StoreTable::getCurrentOrderId) // 必须没有订单
|
|
|
|
|
+ .set(StoreTable::getStatus, 1)
|
|
|
|
|
+ .set(StoreTable::getCurrentOrderId, dto.getOrderId());
|
|
|
|
|
+
|
|
|
|
|
+ boolean toUpdateResult = this.update(toUpdateWrapper);
|
|
|
|
|
+
|
|
|
|
|
+ if (!toUpdateResult) {
|
|
|
|
|
+ log.warn("换桌失败:目标桌号已被占用(可能被其他用户扫码),toTableId={}", dto.getToTableId());
|
|
|
|
|
+ // 回滚原桌号的更新
|
|
|
|
|
+ LambdaUpdateWrapper<StoreTable> rollbackWrapper = new LambdaUpdateWrapper<>();
|
|
|
|
|
+ rollbackWrapper.eq(StoreTable::getId, dto.getFromTableId())
|
|
|
|
|
+ .set(StoreTable::getStatus, 1)
|
|
|
|
|
+ .set(StoreTable::getCurrentOrderId, dto.getOrderId());
|
|
|
|
|
+ this.update(rollbackWrapper);
|
|
|
|
|
+ throw new RuntimeException("目标桌号已被占用,请选择其他桌号");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 创建换桌记录(只有在成功更新后才记录)
|
|
|
|
|
+ StoreTableLog tableLog = new StoreTableLog();
|
|
|
|
|
+ tableLog.setStoreId(fromTable.getStoreId());
|
|
|
|
|
+ tableLog.setOrderId(dto.getOrderId());
|
|
|
|
|
+ tableLog.setFromTableId(dto.getFromTableId());
|
|
|
|
|
+ tableLog.setFromTableNumber(fromTable.getTableNumber());
|
|
|
|
|
+ tableLog.setToTableId(dto.getToTableId());
|
|
|
|
|
+ tableLog.setToTableNumber(toTable.getTableNumber());
|
|
|
|
|
+ tableLog.setChangeReason(dto.getChangeReason());
|
|
|
|
|
+ tableLog.setCreatedUserId(userId);
|
|
|
|
|
+ storeTableLogMapper.insert(tableLog);
|
|
|
|
|
+
|
|
|
|
|
+ log.info("换桌成功:订单{}从桌号{}换到桌号{}", dto.getOrderId(), dto.getFromTableId(), dto.getToTableId());
|
|
|
|
|
+ return true;
|
|
|
|
|
+
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ // 释放分布式锁
|
|
|
|
|
+ baseRedisService.unlock(lockKey, lockIdentifier);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public List<StoreTableStatusVO> batchQueryTableStatus(List<Integer> tableIds) {
|
|
|
|
|
+ log.info("StoreTableServiceImpl.batchQueryTableStatus?tableIds={}", tableIds);
|
|
|
|
|
+
|
|
|
|
|
+ if (tableIds == null || tableIds.isEmpty()) {
|
|
|
|
|
+ log.warn("批量查询桌号状态失败:桌号ID列表为空");
|
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ LambdaQueryWrapper<StoreTable> wrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ wrapper.in(StoreTable::getId, tableIds)
|
|
|
|
|
+ .select(StoreTable::getId, StoreTable::getStatus);
|
|
|
|
|
+ List<StoreTable> tables = this.list(wrapper);
|
|
|
|
|
+
|
|
|
|
|
+ // 转换为VO
|
|
|
|
|
+ return tables.stream()
|
|
|
|
|
+ .map(table -> {
|
|
|
|
|
+ StoreTableStatusVO vo = new StoreTableStatusVO();
|
|
|
|
|
+ vo.setId(table.getId());
|
|
|
|
|
+ vo.setStatus(table.getStatus());
|
|
|
|
|
+ return vo;
|
|
|
|
|
+ })
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 从JWT获取当前登录用户ID
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return 用户ID,如果未登录返回null
|
|
|
|
|
+ */
|
|
|
|
|
+ private Integer getCurrentUserId() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ JSONObject userInfo = JwtUtil.getCurrentUserInfo();
|
|
|
|
|
+ if (userInfo != null) {
|
|
|
|
|
+ return userInfo.getInteger("userId");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("获取当前登录用户ID失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|