yeg
2026-09-18 70ea0911ce7519ca802266078624e9fed3559a2c
talent-card-server/src/main/java/com/talentcard/server/business/portal/PortalService.java
@@ -118,7 +118,12 @@
   @Transactional
   public Map<String, Object> newsDetail(Long id) {
      int updated = jdbcTemplate.update("update news_article set view_count = view_count + 1 where id = ? and deleted = 0 and status = 1", id);
      // 浏览计数不能顺手刷新 updated_at:置顶组是按“修改时间”倒序排的,
      // 否则哪篇被点得多,哪篇就被顶到置顶组最前面,看起来像没按修改时间排。
      int updated = jdbcTemplate.update("""
            update news_article set view_count = view_count + 1, updated_at = updated_at
            where id = ? and deleted = 0 and status = 1
            """, id);
      if (updated == 0) {
         throw new BusinessException(ErrorCode.NOT_FOUND, "资讯不存在");
      }
@@ -148,7 +153,11 @@
   @Transactional
   public Map<String, Object> policy(Long id) {
      int updated = jdbcTemplate.update("update policy_article set view_count = view_count + 1 where id = ? and deleted = 0 and status = 1", id);
      // 同上:浏览政策详情不应该改“修改时间”(后台详情页会展示修改人/修改时间)。
      int updated = jdbcTemplate.update("""
            update policy_article set view_count = view_count + 1, updated_at = updated_at
            where id = ? and deleted = 0 and status = 1
            """, id);
      if (updated == 0) {
         throw new BusinessException(ErrorCode.NOT_FOUND, "政策已下架或不存在");
      }
@@ -902,7 +911,7 @@
      String serviceWhere = " where m.deleted = 0 and m.merchant_type_code = ?";
      PageResult<Map<String, Object>> result = page("""
            select m.id, m.merchant_name, m.merchant_type_code as merchant_type, m.contact_mobile, m.cover_url, m.address,
                   m.service_label, m.status, m.sort_no, m.longitude, m.latitude,
                   m.service_label, m.merchant_rights_config, m.status, m.sort_no, m.longitude, m.latitude,
                   mapping.sort_no as topic_sort_no
            from merchant m
            left join premium_topic_merchant mapping on mapping.merchant_id = m.id and mapping.deleted = 0 and mapping.category_key = ?
@@ -914,16 +923,31 @@
         item.put("businessType", merchantType.premiumBusinessType());
         item.put("targetAction", merchantType.premiumBusinessType());
         boolean tagVisible = !TAGLESS_MERCHANT_TYPES.contains(merchantType.code());
         String benefitText = tagVisible ? textOrDefault(row.get("serviceLabel"), "人才专享") : "";
         // 标签只用后台配的:先取商家权益里第一个启用等级的标签,再退回商家服务标签;
         // 都没配就留空(后台标签是必填项,不再兜底"人才专享")。
         String benefitText = tagVisible ? configuredMerchantTag(row.get("merchantRightsConfig"), row.get("serviceLabel")) : "";
         // 没有标签文本时把 visible 置 false,小程序就不会渲染空标签块。
         boolean tagPresent = tagVisible && !benefitText.isBlank();
         item.put("benefitText", benefitText);
         item.put("discountText", benefitText);
         item.put("benefitTags", tagVisible ? List.of(benefitText) : List.of());
         item.put("benefitTagVisible", tagVisible);
         item.put("benefitTags", tagPresent ? List.of(benefitText) : List.of());
         item.put("benefitTagVisible", tagPresent);
         item.remove("merchantRightsConfig");
         return item;
      }).toList();
      return new PageResult<>(records, result.page(), result.size(), result.total());
   }
   /** 列表标签只用后台配置:商家权益里第一个启用等级的标签 → 商家服务标签 → 空(不兜底默认文案)。 */
   String configuredMerchantTag(Object rightsConfig, Object serviceLabel) {
      for (Map<String, Object> right : merchantRightsConfigs(rightsConfig)) {
         if (!booleanValue(right.get("enabled"))) continue;
         String tag = textOrDefault(right.get("tag"), "");
         if (!tag.isBlank()) return tag;
      }
      return textOrDefault(serviceLabel, "");
   }
   private Map<String, Object> enrichMerchantSearchRow(Map<String, Object> row) {
      Map<String, Object> result = new LinkedHashMap<>(row);
      String merchantType = String.valueOf(result.getOrDefault("merchantType", ""));