Compare commits

...

4 Commits

Author SHA1 Message Date
Tim
61c0336a78 fix: api fix 2025-08-22 16:25:22 +08:00
Tim
0ed9ad2f2a fix: 修复nginx /ws拦截问题 2025-08-22 15:26:41 +08:00
Tim
67e912381b Merge pull request #693 from nagisa77/feature/daily_bugfix_0822_a
fix: 发送信息,携带头像
2025-08-22 13:26:39 +08:00
Tim
d77baa8a93 Merge pull request #692 from nagisa77/feature/daily_bugfix_0822_a
fix: 移动端 ui适配
2025-08-22 13:24:01 +08:00
4 changed files with 79 additions and 76 deletions

View File

@@ -92,7 +92,7 @@ public class SecurityConfig {
cfg.setAllowedHeaders(List.of("*"));
cfg.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", cfg);
source.registerCorsConfiguration("/api/**", cfg);
return source;
}
@@ -104,7 +104,7 @@ public class SecurityConfig {
.exceptionHandling(eh -> eh.accessDeniedHandler(customAccessDeniedHandler))
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.requestMatchers("/ws/**").permitAll()
.requestMatchers("/api/ws/**").permitAll()
.requestMatchers(HttpMethod.POST, "/api/auth/**").permitAll()
.requestMatchers(HttpMethod.GET, "/api/posts/**").permitAll()
.requestMatchers(HttpMethod.GET, "/api/comments/**").permitAll()
@@ -173,7 +173,7 @@ public class SecurityConfig {
response.getWriter().write("{\"error\": \"Invalid or expired token\"}");
return;
}
} else if (!uri.startsWith("/api/auth") && !publicGet && !uri.startsWith("/ws")) {
} else if (!uri.startsWith("/api/auth") && !publicGet && !uri.startsWith("/api/ws")) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json");
response.getWriter().write("{\"error\": \"Missing token\"}");

View File

@@ -41,8 +41,7 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// Registers the "/ws" endpoint, enabling SockJS fallback options so that alternate transports may be used if WebSocket is not available.
registry.addEndpoint("/ws")
registry.addEndpoint("/api/ws")
// 安全改进:使用具体的允许源,而不是通配符
.setAllowedOrigins(
"http://127.0.0.1:8080",

View File

@@ -1,85 +1,83 @@
import { ref } from 'vue';
import { Client } from '@stomp/stompjs';
import SockJS from 'sockjs-client/dist/sockjs.min.js';
import { useRuntimeConfig } from '#app';
import { ref } from 'vue'
import { Client } from '@stomp/stompjs'
import SockJS from 'sockjs-client/dist/sockjs.min.js'
import { useRuntimeConfig } from '#app'
const client = ref(null);
const isConnected = ref(false);
const client = ref(null)
const isConnected = ref(false)
const connect = (token) => {
if (isConnected.value) {
return;
}
if (isConnected.value) {
return
}
const config = useRuntimeConfig();
const API_BASE_URL = config.public.apiBaseUrl;
const socketUrl = `${API_BASE_URL}/ws`;
const config = useRuntimeConfig()
const API_BASE_URL = config.public.apiBaseUrl
const socketUrl = `${API_BASE_URL}/api/ws`
const socket = new SockJS(socketUrl);
const stompClient = new Client({
webSocketFactory: () => socket,
connectHeaders: {
Authorization: `Bearer ${token}`,
},
debug: function (str) {
},
reconnectDelay: 5000,
heartbeatIncoming: 4000,
heartbeatOutgoing: 4000,
});
const socket = new SockJS(socketUrl)
const stompClient = new Client({
webSocketFactory: () => socket,
connectHeaders: {
Authorization: `Bearer ${token}`,
},
debug: function (str) {},
reconnectDelay: 5000,
heartbeatIncoming: 4000,
heartbeatOutgoing: 4000,
})
stompClient.onConnect = (frame) => {
isConnected.value = true;
};
stompClient.onConnect = (frame) => {
isConnected.value = true
}
stompClient.onStompError = (frame) => {
console.error('WebSocket STOMP error:', frame);
};
stompClient.onStompError = (frame) => {
console.error('WebSocket STOMP error:', frame)
}
stompClient.activate();
client.value = stompClient;
};
stompClient.activate()
client.value = stompClient
}
const disconnect = () => {
if (client.value) {
isConnected.value = false;
client.value.deactivate();
client.value = null;
}
};
if (client.value) {
isConnected.value = false
client.value.deactivate()
client.value = null
}
}
const subscribe = (destination, callback) => {
if (!isConnected.value || !client.value || !client.value.connected) {
return null;
}
if (!isConnected.value || !client.value || !client.value.connected) {
return null
}
try {
const subscription = client.value.subscribe(destination, (message) => {
try {
if (destination.includes('/queue/unread-count')) {
callback(message);
} else {
const parsedMessage = JSON.parse(message.body);
callback(parsedMessage);
}
} catch (error) {
callback(message);
}
});
return subscription;
} catch (error) {
return null;
}
};
try {
const subscription = client.value.subscribe(destination, (message) => {
try {
if (destination.includes('/queue/unread-count')) {
callback(message)
} else {
const parsedMessage = JSON.parse(message.body)
callback(parsedMessage)
}
} catch (error) {
callback(message)
}
})
return subscription
} catch (error) {
return null
}
}
export function useWebSocket() {
return {
client,
isConnected,
connect,
disconnect,
subscribe,
};
}
return {
client,
isConnected,
connect,
disconnect,
subscribe,
}
}

View File

@@ -281,7 +281,13 @@ watch(isConnected, (newValue) => {
subscription = subscribe(`/topic/conversation/${conversationId}`, (message) => {
// 避免重复显示当前用户发送的消息
if (message.sender.id !== currentUser.value.id) {
messages.value.push(message)
messages.value.push({
...message,
src: message.sender.avatar,
iconClick: () => {
navigateTo(`/users/${message.sender.id}`, { replace: true })
},
})
// 实时收到消息时自动标记为已读
markConversationAsRead()
setTimeout(() => {