Parcourir la source

修复代码bug

liuchengsen il y a 3 semaines
Parent
commit
e091f7dadc

+ 1 - 1
backend-java/src/main/java/com/pharmacopoeia/repository/UserEventRepository.java

@@ -109,7 +109,7 @@ public interface UserEventRepository extends JpaRepository<UserEvent, Long>,
     Page<Object[]> countByUserIpPaged(@Param("startTime") Instant startTime,
                                        @Param("endTime") Instant endTime, Pageable pageable);
 
-    /** ??????????? */
+    /** 获取所有去重事件类型,供前端筛选 */
     @Query("SELECT DISTINCT e.eventType FROM UserEvent e ORDER BY e.eventType")
     List<String> findDistinctEventTypes();
 }

+ 4 - 0
backend-java/src/main/java/com/pharmacopoeia/security/JwtAuthFilter.java

@@ -75,6 +75,10 @@ public class JwtAuthFilter extends OncePerRequestFilter {
                     log.debug("Token parse failed: {}", e.getMessage());
                 }
             }
+            if (authProperties.isEnabled() && !isPublicPath(request.getRequestURI())) {
+                send401(response, "未提供认证 token");
+                return;
+            }
             filterChain.doFilter(request, response);
         } finally {
             SecurityContextHolder.clearContext();

+ 14 - 10
backend-java/src/main/java/com/pharmacopoeia/security/SecurityConfig.java

@@ -36,18 +36,22 @@ public class SecurityConfig {
                 .csrf(AbstractHttpConfigurer::disable)
                 .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
 
-//        if (authProperties.isEnabled()) {
-//            // 生产模式:所有 /api/** 需要鉴权,公开路径仅限登录和静态资源
-//            http.authorizeHttpRequests(auth -> auth
-//                    .requestMatchers("/health", "/api/v1/auth/**").permitAll()
-//                    .requestMatchers("/static/**", "/").permitAll()
-//                    .requestMatchers("/api/**").authenticated()
-//                    .anyRequest().permitAll()
-//            );
-//        } else {
+        if (authProperties.isEnabled()) {
+            // 生产模式:所有 /api/** 需要鉴权,公开路径仅限登录和静态资源
+            http.authorizeHttpRequests(auth -> auth
+                    .requestMatchers("/health",
+                            "/api/v1/auth/**",
+                            "/api/v1/yaodian/**",
+                            "/api/v1/analytics/**")
+                    .permitAll()
+                    .requestMatchers("/static/**", "/", "/favicon.ico").permitAll()
+                    .requestMatchers("/api/**").authenticated()
+                    .anyRequest().permitAll()
+            );
+        } else {
             // 开发模式:全部放行
             http.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
-      //  }
+        }
 
         http.addFilterBefore(rateLimitFilter, UsernamePasswordAuthenticationFilter.class);
         http.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);

+ 1 - 0
backend-java/src/main/resources/application.yml

@@ -96,5 +96,6 @@ logging:
   level:
     com.pharmacopoeia: INFO
     org.springframework.web: WARN
+    org.springframework.security: INFO
   file:
     path: ${LOG_DIR:/var/log/pharmacopoeia}

+ 21 - 19
static/index.html

@@ -218,9 +218,8 @@
     try {
       fetch(API_BASE + '/api/v1/analytics/events', {
         method: 'POST', headers: h, body: JSON.stringify(payload), keepalive: true
-      }).then(function(r){
-      }).catch(function(e){ console.error('[track] error', e); });
-    } catch(e) { console.error('[track] exception', e); }
+      }).catch(function(){});
+    } catch(e) {}
   }
 
   // 自动埋点所有 fetch 调用
@@ -404,28 +403,31 @@
     if(!msgs.length)return;
     renderMessages(msgs);
   }
+  /** 统一渲染 AI 消息的内部 HTML(标签+内容+来源+品牌推荐) */
+  function buildAiInnerHtml(m) {
+    var tag=m.intent||'';
+    var tagHtml=tag?'<div class="tag '+tagClass(tag)+'">'+intentLabel(tag)+'</div>':'<div class="tag tag-fallback">AI 药典助手</div>';
+    var h = tagHtml+'<div class="content">'+md2html(m.content||'')+'</div>';
+    if (m.sources && m.sources.length) {
+      sourcesData = m.sources;
+      h += buildSourceTags();
+      sourcesData = [];
+    }
+    if (m.brand_recommendations && m.brand_recommendations.length) {
+      brandRecsData = m.brand_recommendations;
+      h += buildBrandRecs();
+      brandRecsData = [];
+    }
+    return h;
+  }
+
   function renderMessages(msgs){
     var w=document.getElementById('chat').querySelector('.welcome');if(w)w.remove();
     for(var i=0;i<msgs.length;i++){
       var m=msgs[i],div=document.createElement('div');
       div.className='msg '+m.role;
       if(m.role==='user'){div.textContent=m.content}
-      else{
-        var tag=m.intent||'';
-        var tagHtml=tag?'<div class="tag '+tagClass(tag)+'">'+intentLabel(tag)+'</div>':'<div class="tag tag-fallback">AI 药典助手</div>';
-        div.innerHTML=tagHtml+'<div class="content">'+md2html(m.content)+'</div>';
-        // 恢复历史记录中的来源引用和品牌推荐
-        if (m.sources && m.sources.length) {
-          sourcesData = m.sources;
-          div.innerHTML += buildSourceTags();
-          sourcesData = [];
-        }
-        if (m.brand_recommendations && m.brand_recommendations.length) {
-          brandRecsData = m.brand_recommendations;
-          div.innerHTML += buildBrandRecs();
-          brandRecsData = [];
-        }
-      }
+      else{ div.innerHTML = buildAiInnerHtml(m); }
       document.getElementById('chat').appendChild(div);
     }
     document.getElementById('chat').scrollTop=document.getElementById('chat').scrollHeight;