Browse Source

feat: 自适应app

zhangwl 2 months ago
parent
commit
7bc547eca6

+ 6 - 6
chat-ai-ui-main/src/components/ChatInput.vue

@@ -24,9 +24,9 @@ const sendMessage = () => {
 </script>
 </script>
 <!-- bg-gray-800 -->
 <!-- bg-gray-800 -->
 <template>
 <template>
-  <div class="p-4 space-y-4">
+  <div class="p-2 sm:p-4 space-y-2 sm:space-y-4">
     <!-- 第一行:流式输出、状态指示器、模型选择 -->
     <!-- 第一行:流式输出、状态指示器、模型选择 -->
-    <div class="flex items-center space-x-6">
+    <div class="flex items-center space-x-3 sm:space-x-6">
       <!-- 流式输出开关 -->
       <!-- 流式输出开关 -->
 <!--      <label class="flex items-center space-x-2 text-white cursor-pointer">-->
 <!--      <label class="flex items-center space-x-2 text-white cursor-pointer">-->
 <!--        <input-->
 <!--        <input-->
@@ -141,20 +141,20 @@ const sendMessage = () => {
         v-model="message"
         v-model="message"
         placeholder="输入你的消息..."
         placeholder="输入你的消息..."
         type="text"
         type="text"
-        class="flex-1 p-3 rounded-lg bg-gray-700 text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 border border-gray-600"
+        class="flex-1 p-2 sm:p-3 rounded-lg bg-gray-700 text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 border border-gray-600 text-sm sm:text-base"
       />
       />
       <button
       <button
         @click="sendMessage"
         @click="sendMessage"
         :disabled="!message.trim() || isLoading"
         :disabled="!message.trim() || isLoading"
         :class="[
         :class="[
-          'px-6 py-3 rounded-lg font-medium transition-all duration-200',
+          'px-3 sm:px-6 py-2 sm:py-3 rounded-lg font-medium transition-all duration-200 flex-shrink-0',
           !message.trim() || isLoading
           !message.trim() || isLoading
             ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
             ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
             : 'bg-blue-500 hover:bg-blue-600 text-white cursor-pointer transform hover:scale-105'
             : 'bg-blue-500 hover:bg-blue-600 text-white cursor-pointer transform hover:scale-105'
         ]"
         ]"
       >
       >
-        <div class="flex items-center space-x-2">
-          <span>发送</span>
+        <div class="flex items-center space-x-1 sm:space-x-2">
+          <span class="hidden sm:inline">发送</span>
           <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
           <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
             <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"></path>
             <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"></path>
           </svg>
           </svg>

+ 22 - 21
chat-ai-ui-main/src/components/Header.vue

@@ -52,59 +52,60 @@ const chatStore = useChatStore();
 
 
 <template>
 <template>
   <div
   <div
-    class="py-4 px-6 bg-gray-800 shadow-md flex justify-between items-center"
+    class="py-2 sm:py-4 px-3 sm:px-6 bg-gray-800 shadow-md flex justify-between items-center"
   >
   >
-    <div class="flex items-center space-x-3">
+    <div class="flex items-center space-x-2 sm:space-x-3 min-w-0">
       <!-- 历史对话汉堡按钮 -->
       <!-- 历史对话汉堡按钮 -->
       <button
       <button
         v-if="userStore.userId"
         v-if="userStore.userId"
         @click="chatStore.sidebarOpen = !chatStore.sidebarOpen"
         @click="chatStore.sidebarOpen = !chatStore.sidebarOpen"
-        class="text-gray-400 hover:text-white p-1.5 rounded transition-colors hover:bg-gray-700"
+        class="text-gray-400 hover:text-white p-1 sm:p-1.5 rounded transition-colors hover:bg-gray-700 flex-shrink-0"
         title="历史对话"
         title="历史对话"
       >
       >
         <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
         <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
           <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
           <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
         </svg>
         </svg>
       </button>
       </button>
-      <img :src="robotImage" alt="Chat AI" class="w-8 h-8" />
-      <h1 class="text-lg font-semibold text-white">AI智能问答系统</h1>
+      <img :src="robotImage" alt="Chat AI" class="w-6 h-6 sm:w-8 sm:h-8 flex-shrink-0" />
+      <h1 class="text-sm sm:text-lg font-semibold text-white truncate">AI智能问答系统</h1>
     </div>
     </div>
 
 
     <!-- 用户信息区域 -->
     <!-- 用户信息区域 -->
-    <div class="flex items-center space-x-4">
+    <div class="flex items-center space-x-2 sm:space-x-4 flex-shrink-0">
 
 
       <!-- 新对话按钮 -->
       <!-- 新对话按钮 -->
       <button
       <button
         @click="chatStore.newConversation()"
         @click="chatStore.newConversation()"
-        class="flex items-center space-x-1 text-gray-400 hover:text-green-400 transition-colors duration-200 px-3 py-1 rounded hover:bg-gray-700"
+        class="hidden sm:flex items-center space-x-1 text-gray-400 hover:text-green-400 transition-colors duration-200 px-3 py-1 rounded hover:bg-gray-700"
       >
       >
         <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
         <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
           <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
           <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
         </svg>
         </svg>
         <span>新对话</span>
         <span>新对话</span>
       </button>
       </button>
+
+      <!-- 新对话按钮(手机版) -->
+      <button
+        @click="chatStore.newConversation()"
+        class="sm:hidden text-gray-400 hover:text-green-400 transition-colors duration-200 p-1 rounded hover:bg-gray-700"
+        title="新对话"
+      >
+        <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
+        </svg>
+      </button>
+
       <!-- 用户头像或图标 -->
       <!-- 用户头像或图标 -->
-      <div class="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center">
-        <span class="text-white text-sm font-medium">
+      <div class="w-6 h-6 sm:w-8 sm:h-8 bg-blue-500 rounded-full flex items-center justify-center flex-shrink-0">
+        <span class="text-white text-xs sm:text-sm font-medium">
           {{ (userStore.name || 'U').charAt(0).toUpperCase() }}
           {{ (userStore.name || 'U').charAt(0).toUpperCase() }}
         </span>
         </span>
       </div>
       </div>
 
 
       <!-- 用户名 -->
       <!-- 用户名 -->
-      <span class="text-gray-300 text-sm">
+      <span class="text-gray-300 text-xs sm:text-sm hidden sm:inline">
         {{ userStore.name || '用户' }}
         {{ userStore.name || '用户' }}
       </span>
       </span>
-
-      <!-- 退出按钮 -->
-<!--      <button-->
-<!--        @click="logout"-->
-<!--        class="flex items-center space-x-1 text-gray-400 hover:text-red-400 transition-colors duration-200 px-3 py-1 rounded hover:bg-gray-700"-->
-<!--      >-->
-<!--        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">-->
-<!--          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>-->
-<!--        </svg>-->
-<!--        <span>退出</span>-->
-<!--      </button>-->
     </div>
     </div>
   </div>
   </div>
 </template>
 </template>

+ 24 - 0
chat-ai-ui-main/src/style.css

@@ -1 +1,25 @@
 @import 'tailwindcss';
 @import 'tailwindcss';
+
+/* 竖屏锁定 */
+html {
+  orientation: portrait;
+}
+
+/* 防止横屏 */
+@media (orientation: landscape) {
+  body {
+    display: none;
+  }
+}
+
+/* 移动端优化 */
+@media (max-width: 640px) {
+  body {
+    font-size: 14px;
+  }
+
+  /* 防止缩放 */
+  input, textarea, select {
+    font-size: 16px;
+  }
+}

+ 13 - 13
chat-ai-ui-main/src/views/ChatView.vue

@@ -163,11 +163,11 @@ watch(
       </transition>
       </transition>
 
 
       <!-- 聊天主区域 -->
       <!-- 聊天主区域 -->
-      <div class="flex justify-center px-4 py-6 h-full">
-        <div class="w-full max-w-4xl flex flex-col h-full">
+      <div class="flex justify-center px-2 sm:px-4 py-3 sm:py-6 h-full">
+        <div class="w-full max-w-2xl sm:max-w-4xl flex flex-col h-full">
 
 
         <!-- 聊天消息容器 -->
         <!-- 聊天消息容器 -->
-        <div id="chat-container" class="flex-1 overflow-y-auto space-y-4 mb-4 px-4 py-4 rounded-lg shadow-lg">
+        <div id="chat-container" class="flex-1 overflow-y-auto space-y-2 sm:space-y-4 mb-4 px-2 sm:px-4 py-2 sm:py-4 rounded-lg shadow-lg">
           <!-- 没有对话内容显示的内容 -->
           <!-- 没有对话内容显示的内容 -->
           <div v-if="chatStore.messages.length === 0" class="flex flex-col items-center justify-center h-full text-gray-400">
           <div v-if="chatStore.messages.length === 0" class="flex flex-col items-center justify-center h-full text-gray-400">
             <div class="text-6xl mb-4">💬</div>
             <div class="text-6xl mb-4">💬</div>
@@ -183,8 +183,8 @@ watch(
             :class="msg.role === 'user' ? 'justify-end' : 'justify-start'"
             :class="msg.role === 'user' ? 'justify-end' : 'justify-start'"
           >
           >
             <!-- AI 图标 -->
             <!-- AI 图标 -->
-            <div v-if="msg.role !== 'user'" class="flex-shrink-0 mr-3 mt-1">
-              <div class="w-8 h-8 bg-blue-600 rounded-full flex items-center justify-center text-sm font-semibold">
+            <div v-if="msg.role !== 'user'" class="flex-shrink-0 mr-2 sm:mr-3 mt-1">
+              <div class="w-6 h-6 sm:w-8 sm:h-8 bg-blue-600 rounded-full flex items-center justify-center text-xs sm:text-sm font-semibold">
                 AI
                 AI
               </div>
               </div>
             </div>
             </div>
@@ -192,13 +192,13 @@ watch(
             <!-- 用户消息气泡 -->
             <!-- 用户消息气泡 -->
             <div
             <div
               v-if="msg.role === 'user'"
               v-if="msg.role === 'user'"
-              class="max-w-2xl px-4 py-3 rounded-lg shadow-sm prose prose-invert max-w-none relative bg-blue-600 text-white rounded-br-sm prose-headings:text-white prose-p:text-white prose-strong:text-white prose-em:text-white"
+              class="max-w-xs sm:max-w-sm md:max-w-2xl px-3 sm:px-4 py-2 sm:py-3 rounded-lg shadow-sm prose prose-invert max-w-none relative bg-blue-600 text-white rounded-br-sm prose-headings:text-white prose-p:text-white prose-strong:text-white prose-em:text-white text-sm sm:text-base"
             >
             >
               <div v-html="formatMessage(msg.displayContent || msg.content, msg.role)"></div>
               <div v-html="formatMessage(msg.displayContent || msg.content, msg.role)"></div>
             </div>
             </div>
 
 
             <!-- AI 消息:三阶段分块 -->
             <!-- AI 消息:三阶段分块 -->
-            <div v-else class="flex flex-col gap-2 min-w-0" style="max-width: 42rem">
+            <div v-else class="flex flex-col gap-2 min-w-0" style="max-width: min(100%, 42rem)">
 
 
               <!-- ① 思考块(紫色,可折叠) -->
               <!-- ① 思考块(紫色,可折叠) -->
               <div v-if="msg.thinkingContent" class="rounded-lg border border-purple-700/40 bg-purple-950/50 overflow-hidden">
               <div v-if="msg.thinkingContent" class="rounded-lg border border-purple-700/40 bg-purple-950/50 overflow-hidden">
@@ -253,7 +253,7 @@ watch(
               <!-- ③ 正式回答(灰色气泡) -->
               <!-- ③ 正式回答(灰色气泡) -->
               <div
               <div
                 v-if="msg.displayContent"
                 v-if="msg.displayContent"
-                class="px-4 py-3 rounded-lg shadow-sm prose prose-invert max-w-none relative bg-gray-700 text-white rounded-bl-sm prose-headings:text-gray-100 prose-p:text-gray-100 prose-strong:text-gray-100 prose-em:text-gray-100 prose-code:text-blue-300 prose-code:bg-gray-800 prose-pre:bg-gray-800 prose-blockquote:border-blue-500"
+                class="px-3 sm:px-4 py-2 sm:py-3 rounded-lg shadow-sm prose prose-invert max-w-none relative bg-gray-700 text-white rounded-bl-sm prose-headings:text-gray-100 prose-p:text-gray-100 prose-strong:text-gray-100 prose-em:text-gray-100 prose-code:text-blue-300 prose-code:bg-gray-800 prose-pre:bg-gray-800 prose-blockquote:border-blue-500 text-sm sm:text-base"
               >
               >
                 <div v-html="formatMessage(msg.displayContent, msg.role)"></div>
                 <div v-html="formatMessage(msg.displayContent, msg.role)"></div>
                 <span v-if="msg.isStreaming && msg.phase === 'answer'" class="typing-cursor"></span>
                 <span v-if="msg.isStreaming && msg.phase === 'answer'" class="typing-cursor"></span>
@@ -261,8 +261,8 @@ watch(
             </div>
             </div>
 
 
             <!-- 用户图标 -->
             <!-- 用户图标 -->
-            <div v-if="msg.role === 'user'" class="flex-shrink-0 ml-3">
-              <div class="w-8 h-8 bg-gray-600 rounded-full flex items-center justify-center text-sm font-semibold">
+            <div v-if="msg.role === 'user'" class="flex-shrink-0 ml-2 sm:ml-3">
+              <div class="w-6 h-6 sm:w-8 sm:h-8 bg-gray-600 rounded-full flex items-center justify-center text-xs sm:text-sm font-semibold">
               </div>
               </div>
             </div>
             </div>
@@ -271,12 +271,12 @@ watch(
 
 
           <!-- 等待回复过程:仅在 loading 且还没有任何流式内容时显示 -->
           <!-- 等待回复过程:仅在 loading 且还没有任何流式内容时显示 -->
           <div v-if="chatStore.isLoading && !chatStore.messages.some(m => m.isStreaming && (m.displayContent || m.thinkingDisplayContent || m.searchingItems.length > 0))" class="flex justify-start">
           <div v-if="chatStore.isLoading && !chatStore.messages.some(m => m.isStreaming && (m.displayContent || m.thinkingDisplayContent || m.searchingItems.length > 0))" class="flex justify-start">
-            <div class="flex-shrink-0 mr-3">
-              <div class="w-8 h-8 bg-blue-600 rounded-full flex items-center justify-center text-sm font-semibold">
+            <div class="flex-shrink-0 mr-2 sm:mr-3">
+              <div class="w-6 h-6 sm:w-8 sm:h-8 bg-blue-600 rounded-full flex items-center justify-center text-xs sm:text-sm font-semibold">
                 AI
                 AI
               </div>
               </div>
             </div>
             </div>
-            <div class="bg-gray-700 text-white px-4 py-3 rounded-lg rounded-bl-sm shadow-sm">
+            <div class="bg-gray-700 text-white px-3 sm:px-4 py-2 sm:py-3 rounded-lg rounded-bl-sm shadow-sm text-sm sm:text-base">
               <div class="flex items-center space-x-2">
               <div class="flex items-center space-x-2">
                 <div class="flex space-x-1">
                 <div class="flex space-x-1">
                   <div class="w-2 h-2 bg-gray-400 rounded-full animate-bounce"></div>
                   <div class="w-2 h-2 bg-gray-400 rounded-full animate-bounce"></div>