Parcourir la source

fix chat page

tycoding il y a 1 an
Parent
commit
59a5ee1a0b

+ 1 - 2
langchat-server/src/main/java/cn/tycoding/langchat/server/controller/ConversationController.java

@@ -98,7 +98,6 @@ public class ConversationController {
 
     @PostMapping("/message")
     public R addMessage(@RequestBody LcMessage message) {
-        messageService.addMessage(message);
-        return R.ok();
+        return R.ok(messageService.addMessage(message));
     }
 }

+ 5 - 0
langchat-server/src/main/java/cn/tycoding/langchat/server/entity/LcConversation.java

@@ -23,6 +23,11 @@ public class LcConversation implements Serializable {
     @TableId(type = IdType.ASSIGN_UUID)
     private String id;
 
+    /**
+     * 提示词ID
+     */
+    private String promptId;
+
     /**
      * 用户ID
      */

+ 1 - 1
langchat-server/src/main/java/cn/tycoding/langchat/server/service/MessageService.java

@@ -38,7 +38,7 @@ public interface MessageService extends IService<LcMessage> {
      */
     void delConversation(String conversationId);
 
-    void addMessage(LcMessage message);
+    LcMessage addMessage(LcMessage message);
 
     void clearMessage(String conversationId);
 }

+ 3 - 2
langchat-server/src/main/java/cn/tycoding/langchat/server/service/impl/MessageServiceImpl.java

@@ -50,7 +50,7 @@ public class MessageServiceImpl extends ServiceImpl<MessageMapper, LcMessage> im
         String title = conversation.getTitle();
         if (StrUtil.isBlank(title)) {
             Long count = conversationMapper.selectCount(Wrappers.lambdaQuery());
-            title = "New Chat" + (count + 1);
+            title = "New Chat" + (count == 0 ? "" : count);
         }
         conversation.setTitle(title)
                 .setUserId(AuthUtil.getUserId()).setCreateTime(new Date());
@@ -72,7 +72,7 @@ public class MessageServiceImpl extends ServiceImpl<MessageMapper, LcMessage> im
     }
 
     @Override
-    public void addMessage(LcMessage message) {
+    public LcMessage addMessage(LcMessage message) {
         if (StrUtil.isBlank(message.getConversationId()) && RoleEnum.USER.getName()
                 .equals(message.getRole())) {
             // create new conversation
@@ -83,6 +83,7 @@ public class MessageServiceImpl extends ServiceImpl<MessageMapper, LcMessage> im
 
         message.setCreateTime(new Date());
         baseMapper.insert(message);
+        return message;
     }
 
     @Override

+ 3 - 0
langchat-ui/.env

@@ -8,3 +8,6 @@ VITE_GLOB_OPEN_LONG_REPLY=false
 
 # When you want to use PWA
 VITE_GLOB_APP_PWA=false
+
+# water mark, this no show when value is empty
+VITE_WATER_MARK=LangChat

+ 3 - 3
langchat-ui/src/App.vue

@@ -4,9 +4,9 @@
   import { useLanguage } from '@/hooks/useLanguage';
   import { NWatermark } from 'naive-ui';
 
-  const showWatermark = true;
   const { theme, themeOverrides } = useTheme();
   const { language } = useLanguage();
+  const waterMark = import.meta.env.VITE_WATER_MARK;
 </script>
 
 <template>
@@ -22,8 +22,8 @@
   </n-config-provider>
 
   <NWatermark
-    v-if="showWatermark"
-    content="LangChat"
+    v-if="waterMark !== ''"
+    :content="waterMark"
     cross
     fullscreen
     :z-index="9999"

+ 37 - 7
langchat-ui/src/api/chat.ts

@@ -74,15 +74,45 @@ export function genImage(data: ImageR): Promise<Oss> {
   });
 }
 
-export const ModelList = [
+export const ModelOptions = [
   {
-    label: 'GPT-4',
-    value: 'gpt-4',
-    des: 'ChatGPT 4',
+    value: 'ChatGPT',
+    label: 'ChatGPT',
+    children: [
+      {
+        value: 'gpt-3.5',
+        label: 'GPT-3.5',
+      },
+      {
+        value: 'gpt-4',
+        label: 'GPT-4',
+      },
+    ],
   },
   {
-    label: 'GPT-3',
-    value: 'gpt-3',
-    des: 'ChatGPT 3',
+    value: 'Google',
+    label: 'Google',
+    children: [
+      {
+        value: 'gemini',
+        label: 'Gemini',
+      },
+    ],
   },
 ];
+
+export function findModelLabel(val: string) {
+  const result = ModelOptions.find((option) => {
+    if (option.children) {
+      const child = option.children.find((child) => child.value === val);
+      return !!child;
+    }
+    return option.value === val;
+  });
+
+  return result
+    ? result.children
+      ? result.children.find((child) => child.value === val)?.label
+      : result.label
+    : undefined;
+}

+ 1 - 0
langchat-ui/src/locales/zh-CN.ts

@@ -97,6 +97,7 @@ export default {
     filePlaceholder: '上传图片或者文件内容',
     searchPlaceholder: '搜索会话',
     newChatButton: '新建会话',
+    emptyConversation: '会话列表为空',
   },
   store: {
     siderButton: '提示词商店',

+ 6 - 0
langchat-ui/src/styles/global.less

@@ -25,3 +25,9 @@ body {
 		background: #27272a !important;
 	}
 }
+
+.bold-cascader {
+	.n-base-selection-label {
+		font-weight: bold;
+	}
+}

+ 5 - 9
langchat-ui/src/typings/chat.d.ts

@@ -55,15 +55,11 @@ export interface ChatState {
 }
 
 export type Conversation = {
-  id: string;
-  title: string;
-  appId: string;
-  appName: string;
-  flowId: string;
-  modelId: string;
-  model: string;
-  chatModel: string;
-  createTime: string;
+  id?: string;
+  promptId?: string;
+  userId?: string;
+  title?: string;
+  createTime?: string;
 };
 
 export type Message = {

+ 1 - 0
langchat-ui/src/typings/env.d.ts

@@ -5,4 +5,5 @@ interface ImportMetaEnv {
   readonly VITE_APP_API_BASE_URL: string;
   readonly VITE_GLOB_OPEN_LONG_REPLY: string;
   readonly VITE_GLOB_APP_PWA: string;
+  readonly VITE_WATER_MARK: string;
 }

+ 10 - 10
langchat-ui/src/views/modules/chat/Header.vue

@@ -2,7 +2,7 @@
   import { SvgIcon } from '@/components/common';
   import { useBasicLayout } from '@/hooks/useBasicLayout';
   import { useChatStore } from '@/views/modules/chat/store/useChatStore';
-  import { ModelList } from '@/api/chat';
+  import { findModelLabel, ModelOptions } from '@/api/chat';
   import { computed } from 'vue';
   import { useDialog, useMessage } from 'naive-ui';
   import { t } from '@/locales';
@@ -15,7 +15,7 @@
   const ms = useMessage();
 
   const chatModel = computed(() => {
-    return ModelList.filter((i) => i.value == chatStore.model)[0].label;
+    return findModelLabel(chatStore.model);
   });
 
   function onClear() {
@@ -79,14 +79,14 @@
           <SvgIcon class="text-2xl" icon="solar:list-bold-duotone" />
         </n-button>
 
-        <n-popselect v-model:value="chatStore.model" :options="ModelList" trigger="click">
-          <n-button icon-placement="right">
-            <span class="font-bold">{{ chatModel }}</span>
-            <template #icon>
-              <SvgIcon icon="mingcute:down-fill" />
-            </template>
-          </n-button>
-        </n-popselect>
+        <n-cascader
+          v-model:value="chatStore.model"
+          class="bold-cascader"
+          expand-trigger="hover"
+          :options="ModelOptions"
+          check-strategy="child"
+          :show-path="true"
+        />
       </div>
 
       <div class="flex items-center space-x-2">

+ 6 - 1
langchat-ui/src/views/modules/chat/index.vue

@@ -48,7 +48,7 @@
     // user
     chatId.value = uuidv4();
     const messageData = await chatStore.addMessage(message, 'user', chatId.value);
-    await addMessage(messageData);
+    const data = await addMessage(messageData);
 
     loading.value = true;
     prompt.value = '';
@@ -60,6 +60,11 @@
     // ai
     aiChatId.value = uuidv4();
     await chatStore.addMessage('', 'assistant', aiChatId.value);
+    if (chatStore.curConversation?.id == undefined) {
+      chatStore.curConversation = { id: String(messageData.conversationId) };
+      await chatStore.selectConversation({ id: messageData.conversationId });
+      console.log(chatStore.active);
+    }
     await scrollToBottom();
     await onChat(message);
   }

+ 1 - 1
langchat-ui/src/views/modules/chat/sider/List.vue

@@ -50,7 +50,7 @@
           class="flex flex-col items-center mt-4 text-center text-neutral-300 dark:border-neutral-800"
         >
           <SvgIcon icon="ri:inbox-line" class="mb-2 text-3xl" />
-          <span>No Conversations!</span>
+          <span>{{ t('chat.emptyConversation') }}</span>
         </div>
       </template>
       <template v-else>

+ 10 - 18
langchat-ui/src/views/modules/chat/store/useChatStore.ts

@@ -15,7 +15,7 @@ import { toRaw } from 'vue';
 export const useChatStore = defineStore('chat-store', {
   state: (): ChatState =>
     <ChatState>{
-      model: 'gpt-3',
+      model: 'gpt-3.5',
       active: '',
       isEdit: '',
       siderCollapsed: true,
@@ -53,7 +53,9 @@ export const useChatStore = defineStore('chat-store', {
         if (data && data.length > 0) {
           this.conversations = data;
         } else {
+          this.active = '';
           this.conversations = [];
+          await router.replace({ path: router.currentRoute.value.path, query: {} });
         }
       } finally {
         this.sideIsLoading = false;
@@ -61,22 +63,6 @@ export const useChatStore = defineStore('chat-store', {
       }
     },
 
-    async selectPath(conversationId: string | undefined, promptId: string | undefined) {
-      const query: any = {};
-      const cur = router.currentRoute.value;
-      if (conversationId !== undefined) {
-        query.conversationId = conversationId;
-      }
-      if (promptId !== undefined) {
-        query.promptId = promptId;
-      }
-      if (cur.query.promptId !== undefined) {
-        query.promptId = cur.query.promptId;
-      }
-
-      await router.replace({ path: router.currentRoute.value.path, query });
-    },
-
     /**
      * 设置当前会话窗口数据
      */
@@ -95,7 +81,13 @@ export const useChatStore = defineStore('chat-store', {
       await this.setEdit('');
       this.curConversation = params;
       this.messages = await getMessages(params.id);
-      await this.selectPath(params.id, undefined);
+
+      // replace url path
+      let query: any = { conversationId: params.id };
+      if (params.promptId !== null) {
+        query.promptId = params.promptId;
+      }
+      await router.replace({ path: router.currentRoute.value.path, query });
     },
 
     /**

+ 5 - 2
langchat-ui/src/views/modules/home/components/CardList.vue

@@ -16,9 +16,12 @@
   const router = useRouter();
 
   async function onUse(id: string) {
-    const data = (await addConversation({})) as Conversation;
+    const data = (await addConversation({ promptId: id })) as Conversation;
     chatStore.curConversation = data;
-    await router.push({ name: 'Chat', query: { conversationId: data.id, promptId: id } });
+    await router.push({
+      name: 'Chat',
+      query: { conversationId: data.id, promptId: data.id },
+    });
     chatStore.active = '';
   }
 </script>