Răsfoiți Sursa

Merge branch 'sit' into sit-OrderFood

lutong 1 lună în urmă
părinte
comite
6e0b74eafc
32 a modificat fișierele cu 587 adăugiri și 40 ștergeri
  1. 4 0
      alien-entity/src/main/java/shop/alien/entity/store/LifeCollect.java
  2. 4 0
      alien-entity/src/main/java/shop/alien/entity/store/LifeDiscountCouponUser.java
  3. 4 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreImg.java
  4. 3 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/SubAccountVo.java
  5. 8 1
      alien-entity/src/main/java/shop/alien/mapper/LifeBrowseRecordMapper.java
  6. 5 0
      alien-entity/src/main/java/shop/alien/mapper/StoreContractMapper.java
  7. 1 1
      alien-entity/src/main/java/shop/alien/mapper/StoreImgMapper.java
  8. 10 0
      alien-entity/src/main/java/shop/alien/mapper/StorePlatformUserRoleMapper.java
  9. 9 0
      alien-entity/src/main/resources/mapper/StoreContractMapper.xml
  10. 1 0
      alien-entity/src/main/resources/mapper/StorePlatformUserRoleMapper.xml
  11. 26 0
      alien-lawyer/src/main/java/shop/alien/lawyer/config/NacosConfig.java
  12. 14 0
      alien-lawyer/src/main/java/shop/alien/lawyer/util/AliSms.java
  13. 38 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformUserRoleController.java
  14. 3 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/dto/UpdateAccountDto.java
  15. 2 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/StorePlatformUserRoleService.java
  16. 10 9
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StoreContractServiceImpl.java
  17. 65 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformUserRoleServiceImpl.java
  18. 61 14
      alien-store/src/main/java/shop/alien/store/aspect/AiAuditAspect.java
  19. 72 10
      alien-store/src/main/java/shop/alien/store/controller/AiSearchController.java
  20. 20 0
      alien-store/src/main/java/shop/alien/store/controller/LifeCollectController.java
  21. 2 2
      alien-store/src/main/java/shop/alien/store/controller/StoreCuisineController.java
  22. 2 2
      alien-store/src/main/java/shop/alien/store/controller/StorePriceController.java
  23. 10 0
      alien-store/src/main/java/shop/alien/store/service/LifeDiscountCouponService.java
  24. 10 0
      alien-store/src/main/java/shop/alien/store/service/StoreBannerService.java
  25. 150 0
      alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponServiceImpl.java
  26. 3 0
      alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponStoreFriendServiceImpl.java
  27. 1 0
      alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponUserServiceImpl.java
  28. 2 0
      alien-store/src/main/java/shop/alien/store/service/impl/LifeGroupPackageServiceImpl.java
  29. 22 0
      alien-store/src/main/java/shop/alien/store/service/impl/StoreBannerServiceImpl.java
  30. 23 0
      alien-store/src/main/java/shop/alien/store/service/impl/StoreInfoServiceImpl.java
  31. 1 1
      alien-store/src/main/java/shop/alien/store/service/impl/StoreOfficialAlbumServiceImpl.java
  32. 1 0
      alien-store/src/main/java/shop/alien/store/service/impl/StorePlatformBenefitsServiceImpl.java

+ 4 - 0
alien-entity/src/main/java/shop/alien/entity/store/LifeCollect.java

@@ -53,4 +53,8 @@ public class LifeCollect {
     @ApiModelProperty(value = "修改人ID")
     @TableField("updated_user_id")
     private Integer updatedUserId;
+
+    @ApiModelProperty(value = "优惠券发放标记:0-未发放,1-已发放")
+    @TableField("coupon_issued_flag")
+    private Integer couponIssuedFlag;
 }

+ 4 - 0
alien-entity/src/main/java/shop/alien/entity/store/LifeDiscountCouponUser.java

@@ -92,6 +92,10 @@ public class LifeDiscountCouponUser extends Model<LifeDiscountCouponUser> {
     @TableField("voucher_id")
     private String voucherId;
 
+    @ApiModelProperty(value = "发放来源:1-手动领取,2-收藏店铺,3-好评送券,4-好友赠送,5-平台发放")
+    @TableField("issue_source")
+    private Integer issueSource;
+
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 4 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreImg.java

@@ -88,4 +88,8 @@ public class StoreImg extends Model<StoreImg> {
     @ApiModelProperty(value = "活动类型:COMMENT-评论有礼,MARKETING-营销活动")
     @TableField(exist = false)
     private String activityType;
+
+    @ApiModelProperty(value = "图片状态:0-未审核,1-审核通过,2-审核未通过")
+    @TableField("img_status")
+    private Integer imgStatus;
 }

+ 3 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/SubAccountVo.java

@@ -16,6 +16,9 @@ import lombok.Data;
 @ApiModel(value = "SubAccountVo对象", description = "子账号信息VO")
 public class SubAccountVo {
 
+    @ApiModelProperty(value = "中间表id(子账号id)")
+    private Integer id;
+
     @ApiModelProperty(value = "用户ID")
     private Integer userId;
 

+ 8 - 1
alien-entity/src/main/java/shop/alien/mapper/LifeBrowseRecordMapper.java

@@ -30,7 +30,14 @@ public interface LifeBrowseRecordMapper extends BaseMapper<LifeBrowseRecord> {
             "Order by lbr.liulan_time desc")
     List<Map<String, Object>> getGroupBuyBrowseRecordByUserId(String userId);
 
-    @Select("select lbr.id,lud.*,lud.id dynamicsId,lbr.liulan_date liulanDate\n" +
+    @Select("select lbr.id, lud.id dynamicsId, IFNULL(lud.cover_image, '') coverImage, lbr.liulan_date liulanDate, " +
+            "lud.phone_id phoneId, lud.title, lud.context, lud.image_path imagePath, lud.address, " +
+            "lud.address_context addressContext, lud.address_name addressName, lud.liulan_count liulanCount, " +
+            "lud.dianzan_count dianzanCount, lud.type, lud.draft, lud.created_time createdTime, lud.updated_time updatedTime, " +
+            "lud.address_province addressProvince, lud.top_status topStatus, lud.top_time topTime, " +
+            "lud.enable_status enableStatus, lud.expert_id expertId, lud.business_id businessId, " +
+            "lud.transfer_count transferCount, lud.reality_count realityCount, lud.check_flag checkFlag, " +
+            "lud.ai_task_id aiTaskId, lud.reason, lud.delete_flag deleteFlag\n" +
             "from life_browse_record lbr \n" +
             "inner join life_user_dynamics lud on lud.id = lbr.dynamics_id \n" +
             "and lud.delete_flag = 0 and lbr.delete_flag = 0 \n" +

+ 5 - 0
alien-entity/src/main/java/shop/alien/mapper/StoreContractMapper.java

@@ -1,5 +1,6 @@
 package shop.alien.mapper;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -8,6 +9,8 @@ import org.apache.ibatis.annotations.Param;
 import shop.alien.entity.store.StoreContract;
 import shop.alien.entity.store.vo.StoreContractVo;
 
+import java.util.List;
+
 /**
  * 合同 Mapper 接口
  *
@@ -32,5 +35,7 @@ public interface StoreContractMapper extends BaseMapper<StoreContract> {
             @Param("status") Integer status,
             @Param("storeId") Integer storeId
     );
+
+    String selectSigningStatus(@Param("storeId") Integer storeId);
 }
 

+ 1 - 1
alien-entity/src/main/java/shop/alien/mapper/StoreImgMapper.java

@@ -75,7 +75,7 @@ public interface StoreImgMapper extends BaseMapper<StoreImg> {
             "#{albumId}" +
             "</foreach>" +
             "</if>" +
-            "ORDER BY si.updated_time DESC" +
+            "ORDER BY si.img_sort ASC" +
             "</script>")
     List<StoreImg> selectOfficialAlbumImgWithName(@Param("storeId") Integer storeId,
                                                    @Param("imgType") Integer imgType,

+ 10 - 0
alien-entity/src/main/java/shop/alien/mapper/StorePlatformUserRoleMapper.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
 import shop.alien.entity.store.StorePlatformUserRole;
 import shop.alien.entity.store.vo.SubAccountListVo;
 import shop.alien.entity.store.vo.SubAccountVo;
@@ -47,5 +48,14 @@ public interface StorePlatformUserRoleMapper extends BaseMapper<StorePlatformUse
                                                 @Param("accountId") String accountId,
                                                 @Param("phone") String phone,
                                                 @Param("status") Integer status);
+
+    /**
+     * 回滚删除操作:恢复角色关联记录
+     *
+     * @param id 记录ID
+     * @return 更新影响的行数
+     */
+    @Update("UPDATE store_platform_user_role SET delete_flag = 0 WHERE id = #{id} AND delete_flag = 1")
+    int rollbackDeleteById(@Param("id") Long id);
 }
 

+ 9 - 0
alien-entity/src/main/resources/mapper/StoreContractMapper.xml

@@ -81,4 +81,13 @@
         ORDER BY cm.created_time DESC
     </select>
 
+    <select id="selectSigningStatus" resultType="java.lang.String">
+        SELECT signing_status
+        FROM store_contract
+        WHERE store_id = #{storeId}
+        AND delete_flag = 0
+        ORDER BY created_time DESC
+        LIMIT 1
+    </select>
+
 </mapper>

+ 1 - 0
alien-entity/src/main/resources/mapper/StorePlatformUserRoleMapper.xml

@@ -7,6 +7,7 @@
     <!-- 根据店铺ID查询子账号列表(连表查询) -->
     <select id="querySubAccounts" resultType="shop.alien.entity.store.vo.SubAccountVo">
         SELECT
+            spur.id AS id,
             sur.id AS userId,
             spur.account_name AS accountName,
             sur.phone AS phone,

+ 26 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/config/NacosConfig.java

@@ -0,0 +1,26 @@
+package shop.alien.lawyer.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @author ssk
+ * @version 1.0
+ * @date 2025/11/6 13:39
+ */
+@Data
+@Component
+@RefreshScope
+public class NacosConfig {
+
+    /**
+     * 测试手机号
+     */
+    @Value("${ali.sms.testPhone}")
+    private List<String> testPhone;
+
+}

+ 14 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/util/AliSms.java

@@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 import shop.alien.entity.store.StoreVerificationCode;
+import shop.alien.lawyer.config.NacosConfig;
 import shop.alien.mapper.StoreVerificationCodeMapper;
 import shop.alien.util.common.RandomCreateUtil;
 import shop.alien.lawyer.config.BaseRedisService;
@@ -33,6 +34,8 @@ public class AliSms {
 
     private final StoreVerificationCodeMapper storeVerificationCodeMapper;
 
+    private final NacosConfig nacosConfig;
+
     @Value("${ali.sms.accessKeyId}")
     private String accessKeyId;
 
@@ -60,12 +63,23 @@ public class AliSms {
             // -----------------测试用手机号--------------------------------------------------------------------------------------------
             List<String> phoneList = Arrays.asList("19999990001", "19999990002", "19999990003", "19999990004", "19999990005", "19999990006", "19999990007", "19999990008", "19999990009", "19999990010",
                     "16666660001", "16666660002", "16666660003", "16666660004", "16666660005", "16666660006", "16666660007", "16666660008", "16666660009", "16666660010",
+                    "18888880001", "18888880002", "18888880003", "18888880004", "18888880005", "18888880006", "18888880007", "18888880008", "18888880009", "18888880010",
                     "17777770001","17777770002","17777770003","17777770004","17777770005","17777770006","17777770007","17777770008","17777770009","17777770010");
             if (phoneList.contains(phone)) {
                 // 验证码发送成功,将验证码保存到redis中 设置60秒过期
                 baseRedisService.setString("verification_lawyer_"+phone,"123456",Long.valueOf(300));
                 return 123456;
             }
+
+
+            //走nacos配置,测试用  优化版本,暂时还是用之前的,直接写死
+//            if (nacosConfig.getTestPhone().contains(phone)) {
+//                // 验证码发送成功,将验证码保存到redis中 设置60秒过期
+//                baseRedisService.setString("verification_lawyer_"+phone,"123456",Long.valueOf(300));
+//                return 123456;
+//            }
+
+
             // -----------------测试用手机号--------------------------------------------------------------------------------------------
 
             Config config = new Config()

+ 38 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformUserRoleController.java

@@ -243,6 +243,44 @@ public class StorePlatformUserRoleController {
         return R.fail("更新子账号信息失败");
     }
 
+
+
+    @ApiOperation("更新子账号信息")
+    @ApiOperationSupport(order = 10)
+    @PlatformOperationLog(
+            module = "账号操作记录",
+            type = "修改子账号",
+            content = "修改子账号,用户ID:#{#p0.userId},手机号:#{#p0.phone},账号名:#{#p0.accountName}"
+    )
+    @PostMapping("/updateSubAccountNew")
+    public R<String> updateSubAccountNew(@RequestBody UpdateAccountDto updateAccountDto) {
+        log.info("StorePlatformUserRoleController.updateSubAccount?userId={}, phone={}, accountName={}, storeId={}, roleId={}",
+                updateAccountDto.getUserId(), updateAccountDto.getPhone(), updateAccountDto.getAccountName(),
+                updateAccountDto.getStoreId(), updateAccountDto.getRoleId());
+
+        if (updateAccountDto.getUserId() == null) {
+            return R.fail("用户ID不能为空");
+        }
+        if (updateAccountDto.getStoreId() == null) {
+            return R.fail("店铺ID不能为空");
+        }
+
+        boolean result = storePlatformUserRoleService.updateSubAccountNew(
+                updateAccountDto.getUserId(),
+                updateAccountDto.getPhone(),
+                updateAccountDto.getAccountName(),
+                updateAccountDto.getStoreId(),
+                updateAccountDto.getRoleId(),
+                updateAccountDto.getId()
+        );
+        if (result) {
+            return R.success("更新子账号信息成功");
+        }
+        return R.fail("更新子账号信息失败");
+    }
+
+
+
     @ApiOperation("查询所有子账号信息(分页)")
     @ApiOperationSupport(order = 11)
     @ApiImplicitParams({

+ 3 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/dto/UpdateAccountDto.java

@@ -14,6 +14,9 @@ import lombok.Data;
 @ApiModel(value = "UpdateAccountDto", description = "更新子账号请求参数")
 public class UpdateAccountDto {
 
+    @ApiModelProperty(value = "中间表id(子账号id)")
+    private Integer id;
+
     @ApiModelProperty(value = "用户ID", required = true)
     private Integer userId;
 

+ 2 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/StorePlatformUserRoleService.java

@@ -123,6 +123,8 @@ public interface StorePlatformUserRoleService extends IService<StorePlatformUser
      */
     boolean updateSubAccount(Integer userId, String phone, String accountName, Integer storeId, Long roleId);
 
+    boolean updateSubAccountNew(Integer userId, String phone, String accountName, Integer storeId, Long roleId,Integer id);
+
     /**
      * 查询所有子账号信息(包含主账号电话)- 分页查询
      * 查询 store_platform_user_role 表中所有的数据

+ 10 - 9
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StoreContractServiceImpl.java

@@ -200,22 +200,23 @@ public class StoreContractServiceImpl implements StoreContractService {
             if (storeId == null) {
                 return R.fail("店铺ID不能为空");
             }
+            String contracts = storeContractMapper.selectSigningStatus(storeId);
 
             // 根据店铺ID查询最新的合同(按创建时间倒序)
-            List<StoreContract> contracts = storeContractMapper.selectList(
-                    new LambdaQueryWrapper<StoreContract>()
-                            .eq(StoreContract::getStoreId, storeId.longValue())
-                            .eq(StoreContract::getDeleteFlag, 0)
-                            .orderByDesc(StoreContract::getCreatedTime)
-                            .last("LIMIT 1")
-            );
+//            List<StoreContract> contracts = storeContractMapper.selectList(
+//                    new LambdaQueryWrapper<StoreContract>()
+//                            .eq(StoreContract::getStoreId, storeId.longValue())
+//                            .eq(StoreContract::getDeleteFlag, 0)
+//                            .orderByDesc(StoreContract::getCreatedTime)
+//                            .last("LIMIT 1")
+//            );
 
             if (contracts == null || contracts.isEmpty()) {
                 return R.fail("该店铺暂无合同");
             }
 
-            StoreContract contract = contracts.get(0);
-            String signingStatus = contract.getSigningStatus();
+//            StoreContract contract = contracts.get(0);
+            String signingStatus = contracts;
             // 将字符串状态转换为数字:已签署=1, 未签署=0, 已到期=2
             Integer statusValue = null;
             if (signingStatus != null) {

+ 65 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformUserRoleServiceImpl.java

@@ -780,6 +780,71 @@ public class StorePlatformUserRoleServiceImpl extends ServiceImpl<StorePlatformU
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean updateSubAccountNew(Integer userId, String phone, String accountName, Integer storeId, Long roleId,Integer id) {
+        try {
+            // 先查询要删除的记录,保存信息以便回滚
+            StorePlatformUserRole oldUserRole = storePlatformUserRoleMapper.selectById(id);
+            if (oldUserRole == null) {
+                log.error("要删除的角色关联记录不存在: id={}", id);
+                return false;
+            }
+            
+            // 逻辑删除记录
+            LambdaUpdateWrapper<StorePlatformUserRole> deleteWrapper = new LambdaUpdateWrapper<>();
+            deleteWrapper.eq(StorePlatformUserRole::getUserId, userId)
+                    .eq(StorePlatformUserRole::getId, id)
+                    .set(StorePlatformUserRole::getDeleteFlag, 1);
+            int deleteResult = storePlatformUserRoleMapper.update(null, deleteWrapper);
+            
+            if (deleteResult > 0) {
+                log.info("成功删除角色关联记录: userId={}, storeId={}, roleId={}", userId, storeId, roleId);
+                
+                // 尝试创建新账号并分配角色
+                R<String> createResult = createAccountAndAssignRole(phone, accountName, storeId, roleId);
+                
+                if (createResult.getCode() == 200) {
+                    log.info("成功创建新账号并分配角色: phone={}, storeId={}, roleId={}", phone, storeId, roleId);
+                    return true;
+                } else {
+                    // 创建失败,执行回滚:恢复删除的记录
+                    log.warn("创建新账号失败,执行回滚操作: phone={}, storeId={}, roleId={}, error={}", 
+                            phone, storeId, roleId, createResult.getMsg());
+                    
+                    int rollbackResult = storePlatformUserRoleMapper.rollbackDeleteById(Long.valueOf(id));
+                    
+                    if (rollbackResult > 0) {
+                        log.info("成功回滚,恢复角色关联记录: id={}, userId={}, storeId={}, roleId={}", 
+                                id, userId, storeId, roleId);
+                    } else {
+                        log.error("回滚失败,无法恢复角色关联记录: id={}, userId={}, storeId={}, roleId={}", 
+                                id, userId, storeId, roleId);
+                    }
+                    return false;
+                }
+            } else {
+                log.error("删除角色关联记录失败: userId={}, id={}", userId, id);
+                return false;
+            }
+        } catch (Exception e) {
+            log.error("更新子账号失败,尝试回滚: userId={}, phone={}, accountName={}, storeId={}, roleId={}, id={}", 
+                    userId, phone, accountName, storeId, roleId, id, e);
+            
+            // 异常情况下也尝试回滚
+            try {
+                int rollbackResult = storePlatformUserRoleMapper.rollbackDeleteById(Long.valueOf(id));
+                if (rollbackResult > 0) {
+                    log.info("异常情况下成功回滚,恢复角色关联记录: id={}", id);
+                }
+            } catch (Exception rollbackException) {
+                log.error("回滚操作也失败: id={}", id, rollbackException);
+            }
+            
+            return false;
+        }
+    }
+
+    @Override
     public IPage<SubAccountListVo> queryAllSubAccounts(Integer pageNum, Integer pageSize, String accountId, String phone, Integer status) {
         try {
             // 创建分页对象

+ 61 - 14
alien-store/src/main/java/shop/alien/store/aspect/AiAuditAspect.java

@@ -1,3 +1,4 @@
+/*
 package shop.alien.store.aspect;
 
 import com.alibaba.fastjson.JSON;
@@ -13,13 +14,17 @@ import shop.alien.entity.store.StorePrice;
 import shop.alien.entity.store.dto.CuisineComboDto;
 import shop.alien.store.util.ai.AiContentModerationUtil;
 
+import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.StringJoiner;
 
+*/
 /**
  * AI 审核切面:拦截美食与通用价目新增/修改接口
- */
+ *//*
+
 @Slf4j
 @Aspect
 @Component
@@ -29,9 +34,11 @@ public class AiAuditAspect {
 
     private final AiContentModerationUtil aiContentModerationUtil;
 
-    /**
+    */
+/**
      * 仅拦截美食新增/修改与通用价目新增/修改接口
-     */
+     *//*
+
     @Pointcut(
             "execution(* shop.alien.store.controller.StoreCuisineController.addCuisineCombo(..))"
                     + " || execution(* shop.alien.store.controller.StoreCuisineController.updateCuisineCombo(..))"
@@ -41,14 +48,16 @@ public class AiAuditAspect {
         // pointcut definition
     }
 
-    /**
+    */
+/**
      * 环绕通知:组合请求参数,获取AI token,并设置审核状态
-     */
+     *//*
+
     @Around("aiAuditPointcut()")
     public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
         Object[] args = joinPoint.getArgs();
 
-        String payload = JSON.toJSONString(args);
+        String payload = extractFieldValues(args);
         log.info("AI审核切面拦截方法: {}, payload={}", joinPoint.getSignature().toShortString(), payload);
 
         List<String> imageUrls = extractImageUrls(args);
@@ -62,9 +71,11 @@ public class AiAuditAspect {
         return joinPoint.proceed(args);
     }
 
-    /**
+    */
+/**
      * AI审核调用:使用文本审核(图片列表暂为空)
-     */
+     *//*
+
     private boolean performAiAudit(String payload, List<String> imageUrls, Object[] args) {
         try {
             // token 目前仅预留,如后续需要可添加到header或payload
@@ -88,9 +99,11 @@ public class AiAuditAspect {
         }
     }
 
-    /**
+    */
+/**
      将审核结果写入入参的status字段(通过=1,不通过=2)
-     */
+     *//*
+
     private void applyStatus(Object[] args, boolean passed) {
         int status = passed ? 1 : 2;
         for (Object arg : args) {
@@ -105,9 +118,11 @@ public class AiAuditAspect {
         }
     }
 
-    /**
+    */
+/**
      * 将审核失败原因写入入参
-     */
+     *//*
+
     private void applyFailureReason(Object[] args, String reason) {
         String safeReason = reason != null ? reason : "审核未通过";
         for (Object arg : args) {
@@ -122,9 +137,40 @@ public class AiAuditAspect {
         }
     }
 
-    /**
+    */
+/**
+     * 通过反射提取所有参数对象的字段值,用空格拼接成纯文本
+     *//*
+
+    private String extractFieldValues(Object[] args) {
+        StringJoiner joiner = new StringJoiner(" ");
+        for (Object arg : args) {
+            if (arg == null) {
+                continue;
+            }
+            for (Field field : arg.getClass().getDeclaredFields()) {
+                field.setAccessible(true);
+                try {
+                    Object value = field.get(arg);
+                    if (value != null) {
+                        String str = String.valueOf(value);
+                        if (!str.isEmpty()) {
+                            joiner.add(str);
+                        }
+                    }
+                } catch (IllegalAccessException e) {
+                    // skip
+                }
+            }
+        }
+        return joiner.toString();
+    }
+
+    */
+/**
      * 从入参中提取图片URL列表;images字段为JSON字符串数组
-     */
+     *//*
+
     private List<String> extractImageUrls(Object[] args) {
         for (Object arg : args) {
             if (arg instanceof CuisineComboDto) {
@@ -153,3 +199,4 @@ public class AiAuditAspect {
     }
 }
 
+*/

+ 72 - 10
alien-store/src/main/java/shop/alien/store/controller/AiSearchController.java

@@ -20,18 +20,19 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.client.RestTemplate;
 import shop.alien.entity.result.R;
-import shop.alien.entity.store.LifeBlacklist;
-import shop.alien.entity.store.StoreImg;
-import shop.alien.entity.store.StoreUser;
+import shop.alien.entity.store.*;
+import shop.alien.entity.store.vo.StoreBannerVo;
 import shop.alien.entity.store.vo.StoreInfoVo;
-import shop.alien.entity.store.CommonRating;
 import shop.alien.mapper.CommonRatingMapper;
 import shop.alien.mapper.LifeBlacklistMapper;
 import shop.alien.mapper.StoreImgMapper;
 import shop.alien.mapper.StoreUserMapper;
 import shop.alien.store.annotation.TrackEvent;
 import shop.alien.store.service.CommonRatingService;
+import shop.alien.store.service.StoreBannerService;
 import shop.alien.store.service.StoreImgService;
+import shop.alien.store.service.StoreInfoService;
+import shop.alien.entity.store.vo.StoreBusinessStatusVo;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 
 import java.time.Instant;
@@ -63,8 +64,10 @@ public class AiSearchController {
 
     private final RestTemplate restTemplate;
     private final StoreImgService storeImgService;
+    private final StoreBannerService storeBannerService;
     private final CommonRatingService commonRatingService;
     private final CommonRatingMapper commonRatingMapper;
+    private final StoreInfoService storeInfoService;
 
     private final LifeBlacklistMapper lifeBlacklistMapper;
 
@@ -105,9 +108,14 @@ public class AiSearchController {
             List<StoreInfoVo> relatedResult = convertToStoreInfoList(jsonObject.getJSONArray("related_results"),map.get("userId"));
             List<StoreInfoVo> matchedResult = convertToStoreInfoList(jsonObject.getJSONArray("matched_results"),map.get("userId"));
 
-            // 查找图片并设置到result中(图片类型1-入口图)
-            fillStoreImages(relatedResult, 1);
-            fillStoreImages(matchedResult, 1);
+            // 并发处理图片和营业时间,提升性能
+            CompletableFuture<Void> relatedImageFuture = CompletableFuture.runAsync(() -> fillStoreImages(relatedResult, 1));
+            CompletableFuture<Void> matchedImageFuture = CompletableFuture.runAsync(() -> fillStoreImages(matchedResult, 1));
+            CompletableFuture<Void> relatedBusinessHoursFuture = CompletableFuture.runAsync(() -> fillBusinessHours(relatedResult));
+            CompletableFuture<Void> matchedBusinessHoursFuture = CompletableFuture.runAsync(() -> fillBusinessHours(matchedResult));
+            
+            // 等待所有任务完成
+            CompletableFuture.allOf(relatedImageFuture, matchedImageFuture, relatedBusinessHoursFuture, matchedBusinessHoursFuture).join();
 
             // 合并两个列表
 //            List<StoreInfoVo> relatedResults = new ArrayList<>();
@@ -116,6 +124,14 @@ public class AiSearchController {
 //            relatedResults.addAll(relatedResult);
             jsonObject1.put("matchedRecords", matchedResult);
             jsonObject1.put("relatedRecords", relatedResult);
+            // 根据matchedResult中的business_section_name去插入到storeBanners中
+            List<String> sectionNames = matchedResult.stream()
+                    .map(StoreInfoVo::getBusinessSectionName)
+                    .filter(StringUtils::isNotBlank)
+                    .distinct()
+                    .collect(Collectors.toList());
+            List<StoreBannerVo> storeBanners = storeBannerService.getBannerByAISearch(sectionNames);
+            jsonObject1.put("storeBanners", storeBanners);
 
 
             jsonObject1.put("total", jsonObject.get("total"));
@@ -154,12 +170,13 @@ public class AiSearchController {
             // 模糊搜索:从related_results和matched_results字段获取数据
             List<StoreInfoVo> result = convertToStoreInfoList(jsonObject.getJSONArray("results"),map.get("userId"));
 
-            // 并发处理图片和评论数据,提升性能
+            // 并发处理图片、评论数据和营业时间,提升性能
             CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> fillStoreImages(result, 1));
             CompletableFuture<Void> ratingFuture = CompletableFuture.runAsync(() -> fillRatingCountBatch(result));
+            CompletableFuture<Void> businessHoursFuture = CompletableFuture.runAsync(() -> fillBusinessHours(result));
             
-            // 等待两个任务完成
-            CompletableFuture.allOf(imageFuture, ratingFuture).join();
+            // 等待所有任务完成
+            CompletableFuture.allOf(imageFuture, ratingFuture, businessHoursFuture).join();
 
             jsonObject1.put("records", result);
 
@@ -349,6 +366,51 @@ public class AiSearchController {
     }
 
     /**
+     * 批量填充营业时间到StoreInfoVo列表中
+     * 通过调用storeInfoService.getStoreBusinessStatus方法获取营业时间
+     *
+     * @param result StoreInfoVo列表
+     */
+    private void fillBusinessHours(List<StoreInfoVo> result) {
+        if (result == null || result.isEmpty()) {
+            return;
+        }
+
+        // 遍历result集合,为每个门店调用getStoreBusinessStatus方法
+        for (StoreInfoVo storeInfo : result) {
+            if (storeInfo.getId() != null) {
+                try {
+                    // 调用getStoreBusinessStatus方法获取营业时间
+                    StoreBusinessStatusVo businessStatus = storeInfoService.getStoreBusinessStatus(String.valueOf(storeInfo.getId()));
+                    if (businessStatus != null) {
+                        // 设置营业时间信息到StoreInfoVo中
+                        if (businessStatus.getStoreBusinessInfos() != null && !businessStatus.getStoreBusinessInfos().isEmpty()) {
+                            storeInfo.setStoreBusinessInfos(businessStatus.getStoreBusinessInfos());
+                            // 同时设置到openTime字段(格式化为字符串列表)
+                            List<String> openTimeList = businessStatus.getStoreBusinessInfos().stream()
+                                    .map(info -> {
+                                        if (info.getBusinessDate() != null && info.getStartTime() != null && info.getEndTime() != null) {
+                                            return info.getBusinessDate() + " " + info.getStartTime() + "-" + info.getEndTime();
+                                        }
+                                        return null;
+                                    })
+                                    .filter(time -> time != null)
+                                    .collect(Collectors.toList());
+                            storeInfo.setOpenTime(openTimeList);
+                        }
+                        // 设置营业状态
+                        if (businessStatus.getYyFlag() != null) {
+                            storeInfo.setYyFlag(businessStatus.getYyFlag());
+                        }
+                    }
+                } catch (Exception e) {
+                    log.error("获取门店营业时间失败,storeId: {}", storeInfo.getId(), e);
+                }
+            }
+        }
+    }
+
+    /**
      * 将下划线命名转换为驼峰命名
      * 例如: store_tel -> storeTel, created_time -> createdTime
      */

+ 20 - 0
alien-store/src/main/java/shop/alien/store/controller/LifeCollectController.java

@@ -19,6 +19,7 @@ import shop.alien.mapper.*;
 import shop.alien.mapper.second.SecondGoodsMapper;
 import shop.alien.store.annotation.TrackEvent;
 import shop.alien.store.config.GaoDeMapUtil;
+import shop.alien.store.service.LifeDiscountCouponService;
 import shop.alien.util.common.ListToPage;
 
 import java.text.DecimalFormat;
@@ -54,6 +55,8 @@ public class LifeCollectController {
 
     private final LifeGroupBuyMainMapper lifeGroupBuyMainMapper;
 
+    private final LifeDiscountCouponService lifeDiscountCouponService;
+
     @ApiOperation("收藏列表")
     @ApiOperationSupport(order = 1)
     @ApiImplicitParams({@ApiImplicitParam(name = "page", value = "分页页数", dataType = "String", paramType = "query", required = true),
@@ -230,6 +233,23 @@ public class LifeCollectController {
             LambdaQueryWrapper<LifeCollect> queryWrapper = new LambdaQueryWrapper<>();
             queryWrapper.eq(LifeCollect::getStoreId, lifeCollect.getStoreId());
             storeInfoMapper.update(null, new LambdaUpdateWrapper<StoreInfo>().eq(StoreInfo::getId, lifeCollect.getStoreId()).set(StoreInfo::getCollectNum, lifeCollectMapper.selectCount(queryWrapper)));
+            
+            // 收藏店铺时自动发放优惠券(每种类型一张)
+            if (StringUtils.hasText(lifeCollect.getUserId())) {
+                try {
+                    Integer userId = Integer.parseInt(lifeCollect.getUserId());
+                    // 传入收藏记录ID,用于更新发放标记
+                    int issuedCount = lifeDiscountCouponService.issueCouponsForStoreCollect(userId, lifeCollect.getStoreId(), lifeCollect.getId());
+                    if (issuedCount > 0) {
+                        log.info("收藏店铺自动发放优惠券成功,userId={}, storeId={}, collectId={}, issuedCount={}", 
+                                userId, lifeCollect.getStoreId(), lifeCollect.getId(), issuedCount);
+                    }
+                } catch (NumberFormatException e) {
+                    log.warn("收藏店铺发放优惠券失败:用户ID格式错误,userId={}, storeId={}", lifeCollect.getUserId(), lifeCollect.getStoreId());
+                } catch (Exception e) {
+                    log.error("收藏店铺发放优惠券异常,userId={}, storeId={}, error={}", lifeCollect.getUserId(), lifeCollect.getStoreId(), e.getMessage(), e);
+                }
+            }
         }
 
 

+ 2 - 2
alien-store/src/main/java/shop/alien/store/controller/StoreCuisineController.java

@@ -162,7 +162,7 @@ public class StoreCuisineController {
                 
                 LambdaUpdateWrapper<StoreCuisine> auditUpdateWrapper = new LambdaUpdateWrapper<>();
                 auditUpdateWrapper.eq(StoreCuisine::getId, savedCuisine.getId());
-                auditUpdateWrapper.set(StoreCuisine::getRejectionReason, null);
+                auditUpdateWrapper.set(StoreCuisine::getRejectionReason, auditResult.getFailureReason());
                 auditUpdateWrapper.set(StoreCuisine::getAuditTime, new Date());
                 
                 if (auditResult.isPassed()) {
@@ -290,7 +290,7 @@ public class StoreCuisineController {
                 
                 LambdaUpdateWrapper<StoreCuisine> auditUpdateWrapper = new LambdaUpdateWrapper<>();
                 auditUpdateWrapper.eq(StoreCuisine::getId, updatedCuisine.getId());
-                auditUpdateWrapper.set(StoreCuisine::getRejectionReason, null);
+                auditUpdateWrapper.set(StoreCuisine::getRejectionReason, auditResult.getFailureReason());
                 auditUpdateWrapper.set(StoreCuisine::getAuditTime, new Date());
                 
                 if (auditResult.isPassed()) {

+ 2 - 2
alien-store/src/main/java/shop/alien/store/controller/StorePriceController.java

@@ -192,7 +192,7 @@ public class StorePriceController {
                 
                 LambdaUpdateWrapper<StorePrice> auditUpdateWrapper = new LambdaUpdateWrapper<>();
                 auditUpdateWrapper.eq(StorePrice::getId, savedPrice.getId());
-                auditUpdateWrapper.set(StorePrice::getRejectionReason, null);
+                auditUpdateWrapper.set(StorePrice::getRejectionReason, auditResult.getFailureReason());
                 auditUpdateWrapper.set(StorePrice::getAuditTime, new Date());
                 
                 if (auditResult.isPassed()) {
@@ -321,7 +321,7 @@ public class StorePriceController {
                 
                 LambdaUpdateWrapper<StorePrice> auditUpdateWrapper = new LambdaUpdateWrapper<>();
                 auditUpdateWrapper.eq(StorePrice::getId, updatedPrice.getId());
-                auditUpdateWrapper.set(StorePrice::getRejectionReason, null);
+                auditUpdateWrapper.set(StorePrice::getRejectionReason, auditResult.getFailureReason());
                 auditUpdateWrapper.set(StorePrice::getAuditTime, new Date());
                 
                 if (auditResult.isPassed()) {

+ 10 - 0
alien-store/src/main/java/shop/alien/store/service/LifeDiscountCouponService.java

@@ -168,4 +168,14 @@ public interface LifeDiscountCouponService extends IService<LifeDiscountCoupon>
      * @return List<LifeDiscountCoupon>
      */
     List<LifeDiscountCoupon> getPlatformCoupon(Integer couponId, Integer couponType);
+
+    /**
+     * 收藏店铺时自动发放优惠券(每种类型一张)
+     *
+     * @param userId   用户ID
+     * @param storeId  店铺ID
+     * @param collectId 收藏记录ID(用于更新发放标记)
+     * @return 发放的优惠券数量
+     */
+    int issueCouponsForStoreCollect(Integer userId, String storeId, String collectId);
 }

+ 10 - 0
alien-store/src/main/java/shop/alien/store/service/StoreBannerService.java

@@ -7,6 +7,8 @@ import shop.alien.entity.store.StoreBanner;
 import shop.alien.entity.store.dto.StoreBannerDto;
 import shop.alien.entity.store.vo.StoreBannerVo;
 
+import java.util.List;
+
 /**
  * Banner表 服务类
  *
@@ -34,5 +36,13 @@ public interface StoreBannerService extends IService<StoreBanner> {
      * @return 分页数据
      */
     IPage<StoreBannerVo> pageList(String moduleCode, String moduleName, String status, Integer pageNum, Integer pageSize);
+
+    /**
+     * 根据关键词搜索 Banner
+     *
+     * @param keyword 关键词
+     * @return 搜索结果
+     */
+    List<StoreBannerVo> getBannerByAISearch(List<String> keyword);
 }
 

+ 150 - 0
alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponServiceImpl.java

@@ -70,6 +70,8 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
 
     private final LifeCouponMapper lifeCouponMapper;
 
+    private final LifeCollectMapper lifeCollectMapper;
+
     @Override
     public boolean addDiscountCoupon(LifeDiscountCouponDto lifeDiscountCouponDto) {
         try {
@@ -382,6 +384,20 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
         }
         lifeDiscountCouponVo.setAvailableTimeQuantum(availableTimeQuantumList);
         lifeDiscountCouponVo.setCustomizeUnavailableTimeQuantum(customizeUnavailableTimeQuantumList);
+        
+        // 查询店铺名称
+        if (lifeDiscountCoupon != null && !StringUtils.isEmpty(lifeDiscountCoupon.getStoreId())) {
+            try {
+                Integer storeId = Integer.parseInt(lifeDiscountCoupon.getStoreId());
+                StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
+                if (storeInfo != null && !StringUtils.isEmpty(storeInfo.getStoreName())) {
+                    lifeDiscountCouponVo.setStoreName(storeInfo.getStoreName());
+                }
+            } catch (Exception e) {
+                // 查询店铺信息失败,不影响主流程,静默处理
+            }
+        }
+        
         return lifeDiscountCouponVo;
     }
 
@@ -1764,6 +1780,7 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
             lifeDiscountCouponUser.setStatus(0);
             lifeDiscountCouponUser.setDeleteFlag(0);
             lifeDiscountCouponUser.setCreatedTime(new Date());
+            lifeDiscountCouponUser.setIssueSource(5); // 5-平台发放
             lifeDiscountCouponUsers.add(lifeDiscountCouponUser);
         }
         return lifeDiscountCouponUserService.saveBatch(lifeDiscountCouponUsers);
@@ -1828,4 +1845,137 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
         lifeDiscountCouponLambdaQueryWrapper.eq(LifeDiscountCoupon::getGetStatus, 1);
         return lifeDiscountCouponMapper.selectList(lifeDiscountCouponLambdaQueryWrapper);
     }
+
+    /**
+     * 收藏店铺时自动发放优惠券(每种类型一张)
+     * 
+     * @param userId   用户ID
+     * @param storeId  店铺ID
+     * @param collectId 收藏记录ID(用于更新发放标记)
+     * @return 发放的优惠券数量
+     */
+    @Override
+    public int issueCouponsForStoreCollect(Integer userId, String storeId, String collectId) {
+        if (userId == null || StringUtils.isEmpty(storeId)) {
+            return 0;
+        }
+
+        // 如果提供了收藏记录ID,检查是否已发放过
+        if (!StringUtils.isEmpty(collectId)) {
+            LifeCollect lifeCollect = lifeCollectMapper.selectById(collectId);
+            if (lifeCollect != null && lifeCollect.getCouponIssuedFlag() != null && lifeCollect.getCouponIssuedFlag() == 1) {
+                // 该收藏记录已发放过优惠券,不再重复发放
+                return 0;
+            }
+        }
+
+        try {
+            LocalDate now = LocalDate.now();
+            
+            // 查询该店铺所有开启领取的优惠券(有效期内、有库存、未删除)
+            LambdaQueryWrapper<LifeDiscountCoupon> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(LifeDiscountCoupon::getStoreId, storeId)
+                    .eq(LifeDiscountCoupon::getGetStatus, 1) // 开启领取
+                    .eq(LifeDiscountCoupon::getDeleteFlag, 0) // 未删除
+                    .gt(LifeDiscountCoupon::getSingleQty, 0) // 有库存
+                    .ge(LifeDiscountCoupon::getEndGetDate, now) // 未过期
+                    .eq(LifeDiscountCoupon::getCouponStatus, 1) // 正式状态(非草稿)
+                    .isNotNull(LifeDiscountCoupon::getCouponType) // 必须有优惠券类型
+                    .orderByDesc(LifeDiscountCoupon::getCreatedTime); // 按创建时间降序
+            
+            List<LifeDiscountCoupon> allCoupons = lifeDiscountCouponMapper.selectList(queryWrapper);
+            
+            if (CollectionUtils.isEmpty(allCoupons)) {
+                return 0;
+            }
+
+            // 按 couponType 分组,每种类型只取第一个(最新的)
+            Map<Integer, LifeDiscountCoupon> couponByType = new HashMap<>();
+            for (LifeDiscountCoupon coupon : allCoupons) {
+                Integer couponType = coupon.getCouponType();
+                if (couponType != null && !couponByType.containsKey(couponType)) {
+                    couponByType.put(couponType, coupon);
+                }
+            }
+
+            if (couponByType.isEmpty()) {
+                return 0;
+            }
+
+            // 检查用户已领取的优惠券ID列表(避免重复发放)
+            LambdaQueryWrapper<LifeDiscountCouponUser> userCouponWrapper = new LambdaQueryWrapper<>();
+            userCouponWrapper.eq(LifeDiscountCouponUser::getUserId, userId)
+                    .eq(LifeDiscountCouponUser::getDeleteFlag, 0)
+                    .in(LifeDiscountCouponUser::getCouponId, 
+                        couponByType.values().stream().map(LifeDiscountCoupon::getId).collect(Collectors.toList()));
+            List<LifeDiscountCouponUser> existingCoupons = lifeDiscountCouponUserMapper.selectList(userCouponWrapper);
+            Set<Integer> existingCouponIds = existingCoupons.stream()
+                    .map(LifeDiscountCouponUser::getCouponId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toSet());
+
+            // 发放每种类型的优惠券(每种一张)
+            int issuedCount = 0;
+            for (Map.Entry<Integer, LifeDiscountCoupon> entry : couponByType.entrySet()) {
+                LifeDiscountCoupon coupon = entry.getValue();
+                
+                // 如果用户已领取过该优惠券,跳过
+                if (existingCouponIds.contains(coupon.getId())) {
+                    continue;
+                }
+
+                // 再次检查库存(防止并发问题)
+                if (coupon.getSingleQty() == null || coupon.getSingleQty() <= 0) {
+                    continue;
+                }
+
+                try {
+                    // 创建用户优惠券记录
+                    LifeDiscountCouponUser lifeDiscountCouponUser = new LifeDiscountCouponUser();
+                    lifeDiscountCouponUser.setCouponId(coupon.getId());
+                    lifeDiscountCouponUser.setUserId(userId);
+                    lifeDiscountCouponUser.setReceiveTime(new Date());
+                    
+                    // 设置过期时间:优先使用validDate,如果为null则使用endDate
+                    LocalDate expirationTime = coupon.getValidDate();
+                    if (expirationTime == null && coupon.getEndDate() != null) {
+                        expirationTime = coupon.getEndDate();
+                    }
+                    lifeDiscountCouponUser.setExpirationTime(expirationTime);
+                    lifeDiscountCouponUser.setStatus(Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()));
+                    lifeDiscountCouponUser.setDeleteFlag(0);
+                    lifeDiscountCouponUser.setIssueSource(2); // 2-收藏店铺
+                    
+                    // 插入用户优惠券记录
+                    lifeDiscountCouponUserMapper.insert(lifeDiscountCouponUser);
+                    
+                    // 扣减库存
+                    coupon.setSingleQty(coupon.getSingleQty() - 1);
+                    lifeDiscountCouponMapper.updateById(coupon);
+                    
+                    issuedCount++;
+                } catch (Exception e) {
+                    // 单个优惠券发放失败不影响其他优惠券的发放
+                    // 静默处理,不记录日志,避免日志过多
+                }
+            }
+
+            // 如果发放成功且提供了收藏记录ID,更新收藏记录的发放标记
+            if (issuedCount > 0 && !StringUtils.isEmpty(collectId)) {
+                try {
+                    LifeCollect lifeCollect = new LifeCollect();
+                    lifeCollect.setId(collectId);
+                    lifeCollect.setCouponIssuedFlag(1); // 标记为已发放
+                    lifeCollectMapper.updateById(lifeCollect);
+                } catch (Exception e) {
+                    // 更新标记失败不影响主流程
+                }
+            }
+
+            return issuedCount;
+        } catch (Exception e) {
+            // 异常时静默处理,不影响收藏功能
+            return 0;
+        }
+    }
 }

+ 3 - 0
alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponStoreFriendServiceImpl.java

@@ -390,6 +390,7 @@ public class LifeDiscountCouponStoreFriendServiceImpl extends ServiceImpl<LifeDi
                             lifeDiscountCouponUser.setExpirationTime(lifeDiscountCoupon.getValidDate());
                             // 设置该优惠券的状态为待使用
                             lifeDiscountCouponUser.setStatus(Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()));
+                            lifeDiscountCouponUser.setIssueSource(4); // 4-好友赠送
                             // 将该用户优惠券记录插入到数据库中
                             lifeDiscountCouponUserMapper.insert(lifeDiscountCouponUser);
                         }
@@ -966,6 +967,7 @@ public class LifeDiscountCouponStoreFriendServiceImpl extends ServiceImpl<LifeDi
                     lifeDiscountCouponUser.setExpirationTime(expirationTime);
                     lifeDiscountCouponUser.setStatus(Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()));
                     lifeDiscountCouponUser.setDeleteFlag(0);
+                    lifeDiscountCouponUser.setIssueSource(3); // 3-好评送券
                     lifeDiscountCouponUserMapper.insert(lifeDiscountCouponUser);
                     coupon.setSingleQty(coupon.getSingleQty() - 1);
                     lifeDiscountCouponMapper.updateById(coupon);
@@ -993,6 +995,7 @@ public class LifeDiscountCouponStoreFriendServiceImpl extends ServiceImpl<LifeDi
                     }
                     lifeDiscountCouponUser.setStatus(Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()));
                     lifeDiscountCouponUser.setDeleteFlag(0);
+                    lifeDiscountCouponUser.setIssueSource(3); // 3-好评送券(代金券)
                     lifeDiscountCouponUserMapper.insert(lifeDiscountCouponUser);
                     lifeCoupon.setSingleQty(lifeCoupon.getSingleQty() - 1);
                     lifeCouponMapper.updateById(lifeCoupon);

+ 1 - 0
alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponUserServiceImpl.java

@@ -108,6 +108,7 @@ public class LifeDiscountCouponUserServiceImpl extends ServiceImpl<LifeDiscountC
 
                 //存入状态  待使用:0
                 lifeDiscountCouponUser.setStatus(Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()));
+                lifeDiscountCouponUser.setIssueSource(1); // 1-手动领取
                 lifeDiscountCouponUserMapper.insert(lifeDiscountCouponUser);
             }
             //削减该优惠券库存

+ 2 - 0
alien-store/src/main/java/shop/alien/store/service/impl/LifeGroupPackageServiceImpl.java

@@ -153,6 +153,7 @@ public class LifeGroupPackageServiceImpl extends ServiceImpl<LifeGroupPackageMap
                                     lifeDiscountCouponUser.setExpirationTime(insertedCoupon.getEndDate());
                                     // 设置该优惠券的状态为待使用
                                     lifeDiscountCouponUser.setStatus(Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()));
+                                    lifeDiscountCouponUser.setIssueSource(5); // 5-平台发放(团购套餐补偿)
                                     // 将该用户优惠券记录插入到数据库中
                                     if (lifeDiscountCouponUserMapper.insert(lifeDiscountCouponUser) > 0) {
                                         // 发送通知
@@ -283,6 +284,7 @@ public class LifeGroupPackageServiceImpl extends ServiceImpl<LifeGroupPackageMap
                                     lifeDiscountCouponUser.setExpirationTime(insertedCoupon.getEndDate());
                                     // 设置该优惠券的状态为待使用
                                     lifeDiscountCouponUser.setStatus(Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()));
+                                    lifeDiscountCouponUser.setIssueSource(5); // 5-平台发放(团购套餐补偿)
                                     // 将该用户优惠券记录插入到数据库中
                                     if (lifeDiscountCouponUserMapper.insert(lifeDiscountCouponUser) > 0) {
                                         // 发送通知

+ 22 - 0
alien-store/src/main/java/shop/alien/store/service/impl/StoreBannerServiceImpl.java

@@ -15,6 +15,10 @@ import shop.alien.entity.store.vo.StoreBannerVo;
 import shop.alien.mapper.StoreBannerMapper;
 import shop.alien.store.service.StoreBannerService;
 
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
 /**
  * Banner表 服务实现类
  *
@@ -78,6 +82,24 @@ public class StoreBannerServiceImpl extends ServiceImpl<StoreBannerMapper, Store
         return this.page(page, wrapper).convert(this::toVo);
     }
 
+    @Override
+    public List<StoreBannerVo> getBannerByAISearch(List<String> keyword) {
+        // 去重:过滤空白并按关键词去重
+        List<String> distinctKeywords = (keyword == null || keyword.isEmpty())
+                ? Collections.emptyList()
+                : keyword.stream().filter(StringUtils::isNotBlank).distinct().collect(Collectors.toList());
+
+        LambdaQueryWrapper<StoreBanner> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreBanner::getStatus, "1")
+                .orderByAsc(StoreBanner::getSort)
+                .orderByDesc(StoreBanner::getCreatedTime);
+        // 无关键词时查全部 banner,有关键词时按 module_name 过滤
+        if (distinctKeywords != null && !distinctKeywords.isEmpty()) {
+            wrapper.in(StoreBanner::getModuleName, distinctKeywords);
+        }
+        return this.list(wrapper).stream().map(this::toVo).collect(Collectors.toList());
+    }
+
     private StoreBannerVo toVo(StoreBanner banner) {
         StoreBannerVo vo = new StoreBannerVo();
         BeanUtils.copyProperties(banner, vo);

+ 23 - 0
alien-store/src/main/java/shop/alien/store/service/impl/StoreInfoServiceImpl.java

@@ -2946,6 +2946,24 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
                 );
             }
 
+            // 5.5. 判断门店名称是否改变,如果改变则清空类型为20或21的图片
+            StoreInfo oldStoreInfo = storeInfoMapper.selectById(storeInfodto.getId());
+            if (Objects.nonNull(oldStoreInfo) && StringUtils.isNotEmpty(storeInfodto.getStoreName())) {
+                String oldStoreName = oldStoreInfo.getStoreName();
+                String newStoreName = storeInfodto.getStoreName();
+                // 如果门店名称发生改变
+                if (!Objects.equals(oldStoreName, newStoreName)) {
+                    log.info("门店名称发生改变,清空类型为20或21的图片。门店ID:{},旧名称:{},新名称:{}", 
+                            storeInfodto.getId(), oldStoreName, newStoreName);
+                    // 删除该门店类型为20或21的图片
+                    LambdaUpdateWrapper<StoreImg> imgUpdateWrapper = new LambdaUpdateWrapper<>();
+                    imgUpdateWrapper.eq(StoreImg::getStoreId, storeInfodto.getId())
+                            .in(StoreImg::getImgType, Arrays.asList(20, 21))
+                            .set(StoreImg::getDeleteFlag, 1); // 逻辑删除
+                    storeImgMapper.update(null, imgUpdateWrapper);
+                }
+            }
+
             // 6. 执行更新
             int updateNum = storeInfoMapper.updateById(storeInfo);
 
@@ -3391,6 +3409,11 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
                     map.put("overall_match", dataMap.get("overall_match"));
                     if (Objects.nonNull(matchResults) && !matchResults.isEmpty()) {
                         map.put("match_reason", matchResults.get(0).get("match_reason"));
+
+                        //根据url查询表中图片信息
+//                        LambdaQueryWrapper<StoreImg> eq = new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 20).eq(StoreImg::getImgUrl, imageUrl);
+//                        StoreImg storeImg = storeImgMapper.selectOne(eq);
+//                        storeImg.setImgStatus("true".equals(matchResults.get(0).get("overall_match"))?1:2);
                     }
                 }
             } else {

+ 1 - 1
alien-store/src/main/java/shop/alien/store/service/impl/StoreOfficialAlbumServiceImpl.java

@@ -288,7 +288,7 @@ public class StoreOfficialAlbumServiceImpl extends ServiceImpl<StoreOfficialAlbu
                     return result;
                 }
             }
-            
+            videoQueryWrapper.orderByAsc(StoreVideo::getImgSort);
             List<StoreVideo> videoList = storeVideoMapper.selectList(videoQueryWrapper);
             StoreOfficialAlbumImgVo result = new StoreOfficialAlbumImgVo();
             result.setVideoList(videoList);

+ 1 - 0
alien-store/src/main/java/shop/alien/store/service/impl/StorePlatformBenefitsServiceImpl.java

@@ -264,6 +264,7 @@ public class StorePlatformBenefitsServiceImpl extends ServiceImpl<StorePlatformB
         // 设置该优惠券的状态为待使用
         lifeDiscountCouponUser.setStatus(Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()));
         lifeDiscountCouponUser.setWelfareId(benefitsId);
+        lifeDiscountCouponUser.setIssueSource(5); // 5-平台发放(平台福利)
         lifeDiscountCouponUserMapper.insert(lifeDiscountCouponUser);
 
         if (updateResult > 0) {