feat: 阻止未登录用户使用任何功能
This commit is contained in:
parent
ec96a424c4
commit
3421d0db47
|
|
@ -52,6 +52,7 @@ import { ref, computed, watch, nextTick, onMounted } from "vue";
|
|||
import { storeToRefs } from "pinia";
|
||||
import { useChatStore } from "@/stores/chat";
|
||||
import { useSettingsStore } from "@/stores/settings";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
import ChatHeader from "./ChatHeader.vue";
|
||||
import MessageList from "./MessageList.vue";
|
||||
import ChatInput from "@/components/input/ChatInput.vue";
|
||||
|
|
@ -65,6 +66,7 @@ defineEmits<{
|
|||
|
||||
const chatStore = useChatStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
const authStore = useAuthStore();
|
||||
|
||||
const { currentConversation, isStreaming } = storeToRefs(chatStore);
|
||||
const { settings, sidebarCollapsed } = storeToRefs(settingsStore);
|
||||
|
|
@ -164,6 +166,12 @@ async function handleSend(
|
|||
systemPrompt?: string;
|
||||
},
|
||||
) {
|
||||
// 检查认证状态
|
||||
if (!authStore.isAuthenticated) {
|
||||
window.$toast?.('请先登录', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("handleSend", text, attachments, options);
|
||||
// 检查是否还有正在上传的附件
|
||||
const uploadingAttachments = attachments.filter((a) => a.uploading);
|
||||
|
|
@ -337,6 +345,12 @@ function handleStop() {
|
|||
|
||||
// 重试
|
||||
async function handleRetry(messageId: string) {
|
||||
// 检查认证状态
|
||||
if (!authStore.isAuthenticated) {
|
||||
window.$toast?.('请先登录', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const message = messages.value.find((m: any) => m.id === messageId);
|
||||
if (!message || message.role !== MessageRole.ASSISTANT) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ import AttachmentPreview from "./AttachmentPreview.vue";
|
|||
import { generateId } from "@/utils/helpers";
|
||||
import type { Attachment } from "@/types/chat";
|
||||
import { chatApi } from "@/services/api";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
|
||||
interface AttachmentWithProgress extends Attachment {
|
||||
uploading?: boolean;
|
||||
|
|
@ -216,6 +217,8 @@ const emit = defineEmits<{
|
|||
}>();
|
||||
|
||||
// 响应式状态
|
||||
const authStore = useAuthStore();
|
||||
|
||||
const inputText = ref("");
|
||||
const attachments = ref<AttachmentWithProgress[]>([]);
|
||||
const isFocused = ref(false);
|
||||
|
|
@ -350,6 +353,12 @@ async function addFileAsAttachment(
|
|||
file: File,
|
||||
type: "image" | "file" | "video",
|
||||
) {
|
||||
// 检查认证状态
|
||||
if (!authStore.isAuthenticated) {
|
||||
window.$toast?.('请先登录', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const id = generateId();
|
||||
|
||||
// 创建本地预览URL
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
* Chat UI API 服务
|
||||
* 所有端点都是固定的,后端需要实现这些端点
|
||||
*/
|
||||
import { getAuthHeaders } from './request';
|
||||
|
||||
// API 端点定义(固定)
|
||||
const API_ENDPOINTS = {
|
||||
// 发送消息(流式)
|
||||
|
|
@ -153,7 +155,7 @@ class ChatApi {
|
|||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...getAuthHeaders(),
|
||||
Accept: "text/event-stream",
|
||||
},
|
||||
body: JSON.stringify(openAiRequest),
|
||||
|
|
@ -244,9 +246,7 @@ class ChatApi {
|
|||
|
||||
const response = await fetch(`${this.baseUrl}${API_ENDPOINTS.CHAT}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
headers: getAuthHeaders(),
|
||||
body: JSON.stringify(requestBody),
|
||||
});
|
||||
|
||||
|
|
@ -264,9 +264,7 @@ class ChatApi {
|
|||
async stopChat(messageId?: string) {
|
||||
await fetch(`${this.baseUrl}${API_ENDPOINTS.STOP}/${messageId}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
headers: getAuthHeaders(),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -326,8 +324,13 @@ class ChatApi {
|
|||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
||||
// 获取认证 headers,但不包含 Content-Type(让浏览器为 FormData 自动设置)
|
||||
const authHeaders = getAuthHeaders();
|
||||
const { 'Content-Type': _, ...headersWithoutContentType } = authHeaders;
|
||||
|
||||
const response = await fetch(`${this.baseUrl}${API_ENDPOINTS.UPLOAD}`, {
|
||||
method: "POST",
|
||||
headers: headersWithoutContentType,
|
||||
body: formData,
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
/**
|
||||
* 对话 API 服务层
|
||||
*
|
||||
* 封装所有对话相关的后端 API 调用,支持认证预留
|
||||
* 封装所有对话相关的后端 API 调用
|
||||
*/
|
||||
|
||||
import { authService } from './authService';
|
||||
import { getAuthHeaders } from './request';
|
||||
import type { Conversation, Message, MessageContent, ConversationSettings } from '@/types/chat';
|
||||
|
||||
// API 端点
|
||||
|
|
@ -45,12 +45,7 @@ interface BackendMessage {
|
|||
* 获取请求头(包含认证信息)
|
||||
*/
|
||||
function getHeaders(): Record<string, string> {
|
||||
const headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
// 添加认证 header(预留)
|
||||
const authHeader = authService.getAuthHeader();
|
||||
return { ...headers, ...authHeader };
|
||||
return getAuthHeaders();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -50,7 +50,14 @@ export async function apiRequest(
|
|||
},
|
||||
};
|
||||
|
||||
return fetch(url, config);
|
||||
const response = await fetch(url, config);
|
||||
|
||||
// 401 认证失败提示
|
||||
if (response.status === 401) {
|
||||
window.$toast?.('认证失败,请重新登录', 'error');
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -40,12 +40,18 @@ export const useAuthStore = defineStore('auth', () => {
|
|||
return null;
|
||||
}
|
||||
const data: AuthResponse = await response.json();
|
||||
|
||||
|
||||
if (data.success && data.data) {
|
||||
window.$toast?.(`登录成功, 欢迎 ${data.data.nickname || data.data.username}`, 'success');
|
||||
|
||||
return data.data;
|
||||
}else{
|
||||
window.$toast?.('[Auth] Token 验证失败:Token无效');
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
|
||||
console.error('[Auth] Token 验证失败:', error);
|
||||
return null;
|
||||
}
|
||||
|
|
@ -73,7 +79,6 @@ export const useAuthStore = defineStore('auth', () => {
|
|||
const userInfo = await checkToken(tokenValue);
|
||||
|
||||
if (userInfo) {
|
||||
window.$toast?.(`登录成功, 欢迎 ${userInfo.nickname || userInfo.username}`, 'success');
|
||||
|
||||
token.value = tokenValue;
|
||||
user.value = userInfo;
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"root":["./src/main.ts","./src/components/icons/index.ts","./src/composables/useKeyboard.ts","./src/services/api.ts","./src/services/authService.ts","./src/services/conversationApi.ts","./src/stores/chat.ts","./src/stores/settings.ts","./src/types/chat.ts","./src/utils/helpers.ts","./src/utils/migrateData.ts","./src/App.vue","./src/components/chat/ChatHeader.vue","./src/components/chat/ChatMain.vue","./src/components/chat/MessageList.vue","./src/components/chat/WelcomeScreen.vue","./src/components/input/AttachmentPreview.vue","./src/components/input/ChatInput.vue","./src/components/message/CodeBlock.vue","./src/components/message/MessageActions.vue","./src/components/message/MessageBubble.vue","./src/components/message/components/EChartsContainerNode.vue","./src/components/message/components/Loading.vue","./src/components/message/components/ThinkingNode.vue","./src/components/modals/ConversationSettingsModal.vue","./src/components/modals/SearchModal.vue","./src/components/modals/SettingsModal.vue","./src/components/modals/ShortcutsModal.vue","./src/components/sidebar/ChatSidebar.vue","./src/components/sidebar/ConversationItem.vue","./src/components/ui/FormSelect.vue","./src/components/ui/FormSlider.vue","./src/components/ui/FormSwitch.vue"],"errors":true,"version":"5.9.3"}
|
||||
{"root":["./src/main.ts","./src/components/icons/index.ts","./src/composables/useKeyboard.ts","./src/services/api.ts","./src/services/authService.ts","./src/services/conversationApi.ts","./src/services/request.ts","./src/stores/auth.ts","./src/stores/chat.ts","./src/stores/settings.ts","./src/types/chat.ts","./src/utils/helpers.ts","./src/utils/migrateData.ts","./src/App.vue","./src/components/chat/ChatHeader.vue","./src/components/chat/ChatMain.vue","./src/components/chat/MessageList.vue","./src/components/chat/WelcomeScreen.vue","./src/components/input/AttachmentPreview.vue","./src/components/input/ChatInput.vue","./src/components/message/CodeBlock.vue","./src/components/message/MessageActions.vue","./src/components/message/MessageBubble.vue","./src/components/message/components/EChartsContainerNode.vue","./src/components/message/components/Loading.vue","./src/components/message/components/ThinkingNode.vue","./src/components/modals/ConversationSettingsModal.vue","./src/components/modals/SearchModal.vue","./src/components/modals/SettingsModal.vue","./src/components/modals/ShortcutsModal.vue","./src/components/sidebar/ChatSidebar.vue","./src/components/sidebar/ConversationItem.vue","./src/components/ui/FormSelect.vue","./src/components/ui/FormSlider.vue","./src/components/ui/FormSwitch.vue"],"errors":true,"version":"5.9.3"}
|
||||
Loading…
Reference in New Issue