Просмотр исходного кода

fix: 修复前端页面缺少左侧菜单

Closes https://github.com/ageerle/ruoyi-web/issues/2
ageer 1 месяц назад
Родитель
Сommit
b58d1497f5

+ 174 - 151
src/api/Recognition.ts

@@ -1,165 +1,188 @@
 import { mlog } from "./mjapi";
 
-export interface recType{
-    timeOut:number
-    asrLanguage?:string
-    listener?: (result: string) => void
-    onEnd?: () => void
-    onStart?: () => void
+export interface recType {
+	timeOut: number;
+	asrLanguage?: string;
+	listener?: (result: string) => void;
+	onEnd?: () => void;
+	onStart?: () => void;
 }
 export class Recognition {
-  private recognition: any;
-  private listener?: (result: string) => void;
-  private isStop = false;
-  private recOpt: recType = { timeOut: 2000 };
-  private handleTime: any;
-  private hTime: Date | undefined;
-  private asrLanguage = "cmn-Hans-CN";
-  private onEnd?: () => void;
-  private onStart?: () => void;
-
-  public setListener(fn: (result: string) => void) {
-    this.listener = fn;
-    return this;
-  }
-
-  public setOnEnd(fn: () => void) {
-    this.onEnd = fn;
-    return this;
-  }
-
-  public setOpt(opt: recType) {
-    this.recOpt = opt;
-    if (opt.listener) this.setListener(opt.listener);
-    if (opt.onEnd) this.setOnEnd(opt.onEnd);
-    if (opt.asrLanguage) this.setLang(opt.asrLanguage);
-    if (opt.onStart) this.onStart = opt.onStart;
-    return this;
-  }
-
-  public setLang(lang: string) {
-    this.asrLanguage = lang;
-    return this;
-  }
-
-  public start() {
-    this.isStop = false;
-    if (typeof window === "undefined" || (!window.SpeechRecognition && !window.webkitSpeechRecognition)) {
-      console.warn("当前浏览器不支持 SpeechRecognition,请使用 Chrome 或 Edge");
-      return;
-    }
-
-    if (!this.recognition) {
-      const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
-      this.recognition = recognition;
-    }
-    const recognition = this.recognition;
-
-    recognition.interimResults = true;
-    recognition.lang = this.asrLanguage;
-    recognition.continuous = true;
-
-    this.hTime = new Date();
-    this.handleTime = setInterval(() => this.check(this), this.recOpt.timeOut);
-
-    recognition.addEventListener("result", (event: any) => {
-      let transcript = "";
-      for (let index = 0; index < event.results.length; index++) {
-        const item = event.results[index];
-        if (transcript && this.asrLanguage.includes("Han")) transcript += ",";
-        transcript += (item as unknown as SpeechRecognitionAlternative[])[0]?.transcript;
-      }
-      if (!transcript) return;
-      this.hTime = new Date();
-      this.listener?.(transcript);
-    });
-
-    recognition.addEventListener("end", () => {
-      if (this.isStop) {
-        this.onEnd?.();
-        clearInterval(this.handleTime);
-        return;
-      }
-      setTimeout(() => recognition.start(), 1000); // 避免 Mac 触发安全限制
-    });
-
-    recognition.start();
-    this.onStart?.();
-    return this;
-  }
-
-  public stop() {
-    this.isStop = true;
-    this.recognition?.stop();
-    return this;
-  }
-
-  private check(that: Recognition) {
-    if (!that.hTime) return;
-    const dt = new Date().getTime() - that.hTime.getTime();
-    if (dt > that.recOpt.timeOut) that.stop();
-  }
+	private recognition: any;
+	private listener?: (result: string) => void;
+	private isStop = false;
+	private recOpt: recType = { timeOut: 2000 };
+	private handleTime: any;
+	private hTime: Date | undefined;
+	private asrLanguage = "cmn-Hans-CN";
+	private onEnd?: () => void;
+	private onStart?: () => void;
+
+	public setListener(fn: (result: string) => void) {
+		this.listener = fn;
+		return this;
+	}
+
+	public setOnEnd(fn: () => void) {
+		this.onEnd = fn;
+		return this;
+	}
+
+	public setOpt(opt: recType) {
+		this.recOpt = opt;
+		if (opt.listener) this.setListener(opt.listener);
+		if (opt.onEnd) this.setOnEnd(opt.onEnd);
+		if (opt.asrLanguage) this.setLang(opt.asrLanguage);
+		if (opt.onStart) this.onStart = opt.onStart;
+		return this;
+	}
+
+	public setLang(lang: string) {
+		this.asrLanguage = lang;
+		return this;
+	}
+
+	public start() {
+		this.isStop = false;
+		if (
+			typeof window === "undefined" ||
+			(!window.SpeechRecognition && !window.webkitSpeechRecognition)
+		) {
+			console.warn("当前浏览器不支持 SpeechRecognition,请使用 Chrome 或 Edge");
+			return;
+		}
+
+		if (!this.recognition) {
+			const recognition = new (window.SpeechRecognition ||
+				window.webkitSpeechRecognition)();
+			this.recognition = recognition;
+		}
+		const recognition = this.recognition;
+
+		recognition.interimResults = true;
+		recognition.lang = this.asrLanguage;
+		recognition.continuous = true;
+
+		this.hTime = new Date();
+		this.handleTime = setInterval(() => this.check(this), this.recOpt.timeOut);
+
+		recognition.addEventListener("result", (event: any) => {
+			let transcript = "";
+			for (let index = 0; index < event.results.length; index++) {
+				const item = event.results[index];
+				if (transcript && this.asrLanguage.includes("Han")) transcript += ",";
+				transcript += (item as unknown as SpeechRecognitionAlternative[])[0]
+					?.transcript;
+			}
+			if (!transcript) return;
+			this.hTime = new Date();
+			this.listener?.(transcript);
+		});
+
+		recognition.addEventListener("end", () => {
+			if (this.isStop) {
+				clearInterval(this.handleTime);
+				return;
+			}
+			setTimeout(() => recognition.start(), 1000);
+		});
+
+		recognition.start();
+		this.onStart?.();
+		return this;
+	}
+
+	private check(that: Recognition) {
+		if (!that.hTime) return;
+		const dt = new Date().getTime() - that.hTime.getTime();
+		if (dt > that.recOpt.timeOut) {
+			that.stop(); // 只在 stop 中触发 onEnd
+		}
+	}
+
+	public stop() {
+		if (this.isStop) return this; // 如果已经停止,直接返回
+		this.isStop = true;
+		this.recognition?.stop();
+		clearInterval(this.handleTime);
+		this.onEnd?.(); // 只在这里触发一次 onEnd
+		return this;
+	}
+
+	// public stop() {
+	//   this.isStop = true;
+	//   this.recognition?.stop();
+	//   return this;
+	// }
+
+	// private check(that: Recognition) {
+	//   if (!that.hTime) return;
+	//   const dt = new Date().getTime() - that.hTime.getTime();
+	//   if (dt > that.recOpt.timeOut) that.stop();
+	// }
 }
 
-
 export const supportLanguages: Record<string, string> = {
-  'cmn-Hans-CN': '普通话 (中国大陆)',
-  'cmn-Hans-HK': '普通话 (香港)',
-  'yue-Hant-HK': '粵語 (香港)',
-  'en-US': 'English(United States)',
-  'en-GB': 'English(United Kingdom)',
-  'en-IN': 'English(India)',
-  'es-ES': 'Español',
-  'fr-FR': 'Français',
-  'de-DE': 'Deutsch',
-  'it-IT': 'Italiano',
-  'ja-JP': '日本語',
-  'ko-KR': '한국어',
-  'ar-SA': 'العربية',
-  'pt-BR': 'Português',
-  'ru-RU': 'Русский',
-  'nl-NL': 'Nederlands',
-  'tr-TR': 'Türkçe',
-  'sv-SE': 'Svenska',
-  'hi-IN': 'हिन्दी',
-  'el-GR': 'Ελληνικά',
-  'he-IL': 'עברית',
-  'id-ID': 'Bahasa Indonesia',
-  'pl-PL': 'Polski',
-  'th-TH': 'ไทย',
-  'cs-CZ': 'Čeština',
-  'hu-HU': 'Magyar',
-  'da-DK': 'Dansk',
-  'fi-FI': 'Suomi',
-  'no-NO': 'Norsk',
-  'sk-SK': 'Slovenčina',
-  'uk-UA': 'Українська',
-  'vi-VN': 'Tiếng Việt',
+	"cmn-Hans-CN": "普通话 (中国大陆)",
+	"cmn-Hans-HK": "普通话 (香港)",
+	"yue-Hant-HK": "粵語 (香港)",
+	"en-US": "English(United States)",
+	"en-GB": "English(United Kingdom)",
+	"en-IN": "English(India)",
+	"es-ES": "Español",
+	"fr-FR": "Français",
+	"de-DE": "Deutsch",
+	"it-IT": "Italiano",
+	"ja-JP": "日本語",
+	"ko-KR": "한국어",
+	"ar-SA": "العربية",
+	"pt-BR": "Português",
+	"ru-RU": "Русский",
+	"nl-NL": "Nederlands",
+	"tr-TR": "Türkçe",
+	"sv-SE": "Svenska",
+	"hi-IN": "हिन्दी",
+	"el-GR": "Ελληνικά",
+	"he-IL": "עברית",
+	"id-ID": "Bahasa Indonesia",
+	"pl-PL": "Polski",
+	"th-TH": "ไทย",
+	"cs-CZ": "Čeština",
+	"hu-HU": "Magyar",
+	"da-DK": "Dansk",
+	"fi-FI": "Suomi",
+	"no-NO": "Norsk",
+	"sk-SK": "Slovenčina",
+	"uk-UA": "Українська",
+	"vi-VN": "Tiếng Việt",
 };
 
 function sleep(time: number) {
-  return new Promise((resolve) => setTimeout(resolve, time));
+	return new Promise((resolve) => setTimeout(resolve, time));
 }
 
 //浏览器文字播放
-export async function speakText(content: string, callback: (playing: boolean) => void) {
-  if (!window.speechSynthesis) return;
-  if (speechSynthesis.speaking) {
-    speechSynthesis.cancel();
-    callback(false);
-  }
-
-  await sleep(300);
-
-  const msg = new SpeechSynthesisUtterance(content);
-  msg.lang = 'zh';
-  msg.rate = 1;
-  msg.addEventListener('end', () => {
-    callback(false);
-  });
-  msg.addEventListener('error', () => {
-    callback(false);
-  });
-  callback(true);
-  speechSynthesis.speak(msg);
+export async function speakText(
+	content: string,
+	callback: (playing: boolean) => void
+) {
+	if (!window.speechSynthesis) return;
+	if (speechSynthesis.speaking) {
+		speechSynthesis.cancel();
+		callback(false);
+	}
+
+	await sleep(300);
+
+	const msg = new SpeechSynthesisUtterance(content);
+	msg.lang = "zh";
+	msg.rate = 1;
+	msg.addEventListener("end", () => {
+		callback(false);
+	});
+	msg.addEventListener("error", () => {
+		callback(false);
+	});
+	callback(true);
+	speechSynthesis.speak(msg);
 }

+ 5 - 5
src/components/common/PromptStore/index.vue

@@ -177,15 +177,15 @@ const createColumns = () => {
 				let text, type;
 				switch (row.modelType) {
 					case "1":
-						text = 'Token计费';
+						text = 'Token billing';
 						type = 'success'; // 绿色标签
 						break;
 					case "2":
-						text = '次数计费';
+						text = 'Frequency billing';
 						type = 'info'; // 蓝色标签
 						break;
 					default:
-						text = '未知方式';
+						text = 'Unknown billing';
 						type = 'default'; // 默认灰色标签
 				}
 				// 直接使用导入的 NTag 组件,设置相应的属性
@@ -279,12 +279,12 @@ const loading = ref<boolean>(false)
 					</main>
 				</div>
 			</n-tab-pane>
-			<!-- <n-tab-pane :name="$t('setting.exchange')">
+			<n-tab-pane :name="$t('setting.exchange')">
 				<div class="input-button-container">
 					<n-input v-model:value="redeem" type="text" :placeholder="$t('store.input')" style="width: 70%" />
 					<n-button :bordered="false" type="success" @click="handleRedeemKey">{{  $t('store.redeemKey') }}</n-button>
 				</div>
-			</n-tab-pane> -->
+			</n-tab-pane>
 		</n-tabs>
 	</NModal>
 

+ 2 - 2
src/components/common/Setting/index.vue

@@ -61,14 +61,14 @@ const show = computed({
           </div>
         </NTabPane>
 
-<!--         
+        
        <NTabPane name="chatmsg" tab="chatmsg">
           <template #tab>
             <SvgIcon class="text-lg" icon="mdi:message" />
             <span class="ml-2">{{ $t('setting.message') }}</span>
           </template>
           <aiMsg />
-        </NTabPane> -->
+        </NTabPane>
 
         <!-- <NTabPane name="Config" tab="Config">
           <template #tab>

+ 1 - 1
src/locales/zh-CN.ts

@@ -58,7 +58,7 @@ export default {
     annouce: '公告',
     annouceContent: '本网站为网站所有内容,由用户自行承担。;本网站仅供学习之用。;使用本网站产生的任何问题由用户自行承担。',
     helpTitle: '今天我能为您做些什么呢?',
-    helpcontent: '作为你的智能伙伴,我不仅能帮你写文案、出点子,还能和你聊天、解答问题。想探索我的更多功能?点这里快速了解!',
+    helpcontent: '作为你的智慧伙伴,我不仅可以写文案、出点子,还可以和你聊天、回答问题。想知道我还能做些什么吗? 点击这里快速入门! 您可以将xxx官方网站地址收藏在浏览器中,方便日后使用。;你也可以这样问我:',
     used: '使用',
     refresh: '刷新',
     like: '点赞',

+ 12 - 9
src/styles/lib/highlight.less

@@ -535,7 +535,7 @@ html.dark {
 			color: #fff;
 		}
 		.text{
-			// background-color: #141718;
+			background-color: #141718;
 			p{
 				color: #e2e2e2;
 			}
@@ -553,7 +553,7 @@ html.dark {
 			}
 			.gpts-item{
 				background-color: #232627;
-				border: 1px solid #333435;
+				border: 1px solid #3a3b3c;
 				.name{
 					color: #a7a8a9;
 					&:hover{
@@ -1346,7 +1346,7 @@ position: relative;
 		padding: 0;
 		background-color: #fff;
 		border-bottom-right-radius: 20px;
-		 height: 600px;
+		// height: 156px;
 		.chat-footer{
 			border-bottom-right-radius: 12px;
 			position: relative;
@@ -1357,6 +1357,10 @@ position: relative;
 			border: 2px solid #fff;
 			margin: 0 40px 40px;
 			border-radius: 16px;
+			.items-base {
+				// position: absolute;
+				// top: -70px;
+			}
 			.top-bar{
 				& .left{
 					display: flex;
@@ -1476,7 +1480,7 @@ position: relative;
 	}
 }
 .gpts-box{
-	 color: #494747;
+	color: #494747;
 	h1{
 		font-weight: 700;
 		font-size: 40px;
@@ -1488,7 +1492,7 @@ position: relative;
 		float: left;
 	}
 	.text{
-		// background-color: #e8eaf1;
+		background-color: #e8eaf1;
 		border-radius: 20px;
 		float: left;
 		width: calc(100% - 100px);
@@ -1519,14 +1523,13 @@ position: relative;
 			}
 		}
 		.gpts-item{
-			background-color: #e8eaf1;
+			background-color: #ffffff;
 			border-radius: 10px;
-			// border: 1px solid #e8eaf1;
+			border: 1px solid #e8eaf1;
 			float: left;
-			height: 120px;
 			.n-image{
 				float: left;
-				margin-top: 10px;
+				margin-top: 5px;
 			}
 			.info{
 				white-space: nowrap;

+ 94 - 8
src/views/chat/index.vue

@@ -5,7 +5,7 @@ import type { Ref } from 'vue'
 import { computed, onMounted, onUnmounted, ref,watch,h } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import { storeToRefs } from 'pinia'
-import { NAutoComplete, NButton, NInput, useDialog, useMessage,NAvatar,NModal,NCard,NImage,NTag,NSpace } from 'naive-ui'
+import { NAutoComplete, NButton, NInput, useDialog, useMessage,NAvatar,NModal,NCard,NImage } from 'naive-ui'
 import html2canvas from 'html2canvas'
 import { Message } from './components'
 import { useScroll } from './hooks/useScroll'
@@ -23,7 +23,6 @@ import AiSiderInput from '../mj/aiSiderInput.vue'
 import aiGptInput from '../mj/aiGptInput.vue'
 import { getNotice,readNotice, getInform } from '@/api/notice'
 import to from "await-to-js";
-import { truncate } from 'fs'
 
 let controller = new AbortController()
 
@@ -67,8 +66,6 @@ dataSources.value.forEach((item, index) => {
 })
 
 function handleSubmit() {
-  homeStore.myData.local = "chating"
-  alert(homeStore.myData.local)
   //onConversation() //把这个放到aiGpt
   let message = prompt.value;
   if (!message || message.trim() === '')
@@ -631,9 +628,36 @@ load()
 </script>
 
 <template>
+  <NModal
+  v-model:show="showModal"
+   closable @on-after-leave=""
+   :mask-closable="false"
+    preset="dialog"
+    title="公告详情"
+    positive-text="我已知晓"
+    @positive-click="handleClose"
+   >
+   <div v-html="modalContent"></div>
+  </NModal>
+
   <div class="flex flex-col w-full h-full chat-content" :class="[isMobile? '' : 'chat-content-noMobile']">
+   <!-- v-if="isMobile" -->
+    <!-- <HeaderComponent
+      :haveData="!!dataSources.length"
+      :using-context="usingContext"
+      @export="handleExport"
+      @handle-clear="handleClear"
+    /> -->
+
     <main class="flex-1 overflow-hidden">
 
+      <template v-if="gptConfigStore.myData.kid">
+        <div class="flex  mt-4  text-neutral-300 chat-header">
+           <SvgIcon icon="material-symbols:book" class="mr-1 text-2xl" ></SvgIcon>
+           <span>{{ gptConfigStore.myData.kName }}</span>
+        </div>
+      </template>
+
       <div id="scrollRef" ref="scrollRef" class="h-full overflow-hidden overflow-y-auto">
 
         <div
@@ -646,11 +670,55 @@ load()
 
             </div>
             <div class="gpts-box" v-else>
+              <h1>{{ href }}</h1>
+              <div class="annou" v-if="informContent.length" :style="{'margin-bottom': isMobile ? '15px' : '30px'}">
+                <div class="ai-icon">
+                  <IconSvg icon="chatGPT" :width="isMobile ? '32px' : '64px'" :height="isMobile ? '32px' : '64px'"></IconSvg>
+                </div>
+                <div class="text" :style="{padding: isMobile? '22px 10px' : '22px 68px'}">
+                  <p class="title">{{ t('chat.annouce') }}</p>
+                  <!-- <p v-for="(item,index) in t('chat.annouceContent').split(';')" :key="index">{{ item }}</p> -->
+                  <div v-for="(item, index) in informContent.slice(0, 1)" :key="index" >
+                    <!-- <p style="margin-top: 10px; font-size: 18px">{{ item.noticeTitle }}</p> -->
+                    <div v-html="item.noticeContent"></div>
+                  </div>
+                </div>
+              </div>
               <div class="help" v-if="gptsFilterList && gptsFilterList.length">
-
+                <div class="ai-icon">
+                  <IconSvg icon="chatGPT" :width="isMobile ? '32px' : '64px'" :height="isMobile ? '32px' : '64px'"></IconSvg>
+                </div>
+                <div class="text" :style="{padding: isMobile? '22px 10px' : '22px 68px', 'font-size': isMobile? '14px' : '16px', 'line-height': isMobile? '20px' : '28px'}">
+                  <p class="title">
+                    {{ t('chat.helpTitle') }}
+                  </p>
+                  <p v-for="(item,index) in t('chat.helpcontent').split(';')" :key="index">{{ item }}</p>
+                  <div class="gpts-list">
+                    <div class="refresh" @click="refresh">
+                      <IconSvg icon="refresh"></IconSvg>&nbsp;{{ t('chat.refresh') }}
+                    </div>
+                    <div v-for="v in gptsFilterList" :key="v.name" class="gpts-item" :style="{width: isMobile ? '100%' : 'calc(50% - 20px)', marginRight: '20px', padding: isMobile ? '5px 8px' : '14px 10px', 'margin-bottom': isMobile ? '8px' : '20px'}">
+                      <NImage :src="v.logo" :preview-disabled="true" lazy
+                      class="group-hover:scale-[130%] duration-300 shrink-0 overflow-hidden bg-base object-cover rounded-full bc-avatar w-[80px] h-[80px]" :style="{width: isMobile ? '23px' : '46px', height: isMobile ? '23px' : '46px'}">
+                          <template #placeholder>
+                            <div class="w-full h-full justify-center items-center flex"  >
+                            <SvgIcon icon="line-md:downloading-loop" class="text-[60px] text-green-300"   ></SvgIcon>
+                            </div>
+                          </template>
+                      </NImage>
+                      <div :style="{width: `calc(100% - ${isMobile ? '43px' : '66px'})`, float: 'left', marginLeft: '10px'}">
+                        <p class="info" :title="v.info"> {{ v.info }}</p>
+                        <p @click="goUseGpts(v)" class="name"> {{ t('chat.used') }} {{ v.name }}</p>
+                      </div>
+                    </div>
+                  </div>
+                </div>
               </div>
             </div>
-
+            <!-- <div class="flex items-center justify-center mt-4 text-center text-neutral-300" v-else>
+              <SvgIcon icon="ri:bubble-chart-fill" class="mr-2 text-3xl" />
+              <span>Aha~</span>
+            </div> -->
           </template>
 
           <template v-else>
@@ -688,14 +756,32 @@ load()
         </div>
       </div>
     </main>
-
-    <footer :class="footerClass" class="footer-content" v-if="local!=='chating'">
+    
+    <footer :class="footerClass" class="footer-content" v-if="local!=='draw'">
       <div class="w-full max-w-screen-xl m-auto">
         <aiGptInput @handle-clear="handleClear" @export="handleExport" v-if="['gpt-4o-mini','gpt-3.5-turbo-16k'].indexOf(gptConfigStore.myData.model)>-1 || st.inputme "
          v-model:modelValue="prompt" :disabled="buttonDisabled"
          :searchOptions="searchOptions"  :renderOption="renderOption"
           />
         <div class="flex items-center justify-between space-x-2" v-else>
+          <!--
+          <HoverButton v-if="!isMobile" @click="handleClear">
+            <span class="text-xl text-[#4f555e] dark:text-white">
+              <SvgIcon icon="ri:delete-bin-line" />
+            </span>
+          </HoverButton>
+          <HoverButton v-if="!isMobile" @click="handleExport">
+            <span class="text-xl text-[#4f555e] dark:text-white">
+              <SvgIcon icon="ri:download-2-line" />
+            </span>
+          </HoverButton>
+          <HoverButton @click="toggleUsingContext">
+            <span class="text-xl" :class="{ 'text-[#4b9e5f]': usingContext, 'text-[#a8071a]': !usingContext }">
+              <SvgIcon icon="ri:chat-history-line" />
+            </span>
+          </HoverButton>
+          -->
+
           <NAutoComplete v-model:value="prompt" :options="searchOptions" :render-label="renderOption">
             <template #default="{ handleInput, handleBlur, handleFocus }">
               <NInput

+ 3 - 3
src/views/chat/layout/sider/index.vue

@@ -187,7 +187,7 @@ async function store() {
       </main>
       <Footer v-if="isMobile"></Footer>
     </div>
-    <div class="nav-bar">
+    <!-- <div class="nav-bar">
       <div class="user-info" :style="{ height: isLogin ? '144px' : '90px', bottom: isLogin ? '84px' : '24px' }">
 
         <div v-show="isLogin">
@@ -208,7 +208,7 @@ async function store() {
 
           <div class="user-bottom" @click="store">
             <Button block>
-              <!-- 应用市场 -->
+        
               {{ $t('store.siderButton') }}
             </Button>
           </div>
@@ -232,7 +232,7 @@ async function store() {
           {{ $t('mjset.logout') }}
         </div>
       </div>
-    </div>
+    </div> -->
 
 
     

+ 1 - 1
src/views/knowledge/annex.vue

@@ -245,7 +245,7 @@ function goBack() {
 								</div>
 
 								<div class="upload-warnings">
-									<div class="warning-title"></div>
+									<div class="warning-title">{{ $t("annex.uploadNotes") }}</div>
 									<n-p class="upload-warning">
 										<span class="warning-dot">•</span>
 										{{ $t("annex.friendlyReminder") }}

+ 6 - 6
src/views/knowledge/index.vue

@@ -291,7 +291,7 @@ const columns = ref(createColumns());
 							</n-form-item>
 						</n-gi>
 
-						<!-- <n-gi :span="12">
+						<n-gi :span="12">
 							<n-form-item label="向量库" required>
 								<n-select
 									:options="getVector"
@@ -300,9 +300,9 @@ const columns = ref(createColumns());
 									clearable
 								></n-select>
 							</n-form-item>
-						</n-gi> -->
+						</n-gi>
 
-						<!-- <n-gi :span="12">
+						<n-gi :span="12">
 							<n-form-item label="提问分割符">
 								<n-input
 									v-model:value="formValue.questionSeparator"
@@ -310,7 +310,7 @@ const columns = ref(createColumns());
 									clearable
 								/>
 							</n-form-item>
-						</n-gi> -->
+						</n-gi>
 
 						<n-gi :span="12">
 							<n-form-item label="向量模型" required>
@@ -336,7 +336,7 @@ const columns = ref(createColumns());
 							</n-form-item>
 						</n-gi>
 
-						<!-- <n-gi :span="24">
+						<n-gi :span="24">
 							<n-form-item label="是否公开" label-placement="left">
 								<n-switch
 									size="large"
@@ -348,7 +348,7 @@ const columns = ref(createColumns());
 									<template #unchecked>否</template>
 								</n-switch>
 							</n-form-item>
-						</n-gi> -->
+						</n-gi>
 					</n-grid>
 				</n-form>
 			</n-space>

+ 24 - 23
src/views/mj/aiGptInput.vue

@@ -83,8 +83,6 @@ watch(
 	{ deep: true }
 );
 const handleSubmit = () => {
- 
-
 	if (mvalue.value == "") return;
 	if (checkDisableGpt4(gptConfigStore.myData.model)) {
 		ms.error(t("mj.disableGpt4"));
@@ -217,6 +215,7 @@ const paste = (e: ClipboardEvent) => {
 	let rz = getFileFromClipboard(e);
 	if (rz.length > 0) upFile(rz[0]);
 };
+
 const sendMic = (e: any) => {
 	mlog("sendMic", e);
 	st.value.showMic = false;
@@ -280,22 +279,6 @@ const handleSelectASR = (key: string | number) => {
 	if (key == "asr") goASR();
 	if (key == "whisper") st.value.showMic = true;
 };
-/**
- * 校验字符串的大小
- * @param inputStr 输入的字符
- * @param maxLength 字符串长度
- */
-const truncateText = (inputStr:any, maxLength = 20) => {
-	// 处理空值情况
-	if (!inputStr) return ''
-	// 类型安全校验
-	const str = String(inputStr)
-	// 判断并截断
-	return str.length > maxLength
-		? `${str.slice(0, maxLength)}...`
-		: str
-}
-
 const show = ref(false);
 function handleExport() {
 	emit("export");
@@ -357,9 +340,9 @@ function handleClear() {
 						</template>
 						<template v-else>
 							<SvgIcon icon="heroicons:sparkles" />
-							<span>模型:{{
-								nGptStore.modelLabel ? truncateText(nGptStore.modelLabel,20) : "gpt-4o-mini"
-							}} {{nGptStore.kid?'知识库:'+truncateText(nGptStore.kName,10):''}}</span>
+							<span>{{
+								nGptStore.modelLabel ? nGptStore.modelLabel : "gpt-4o-mini"
+							}}</span>
 						</template>
 						<SvgIcon icon="icon-park-outline:right" />
 					</div>
@@ -420,7 +403,9 @@ function handleClear() {
 					width="28px"
 					height="22px"
 				></IconSvg>
-
+				<!-- <div @click="show = true">
+            {{ $t('store.siderButton') }}
+        </div> -->
 			</div>
 			<input
 				type="file"
@@ -559,8 +544,24 @@ function handleClear() {
 			</NAutoComplete>
 			<div class="send" @click="handleSubmit" v-if="!isMobile">
 				<IconSvg icon="send" width="16px" height="15px"></IconSvg>
+				|
+				<IconSvg icon="money" width="14px" height="24px"></IconSvg>
+				<NPopover trigger="hover">
+					<template #trigger>
+						{{ myToken.modelTokens }}
+					</template>
+					<div class="w-[300px]">
+						{{ $t("mj.tokenInfo1") }}
+						<p class="py-1" v-text="$t('mj.tokenInfo2')"></p>
+						<p class="text-right">
+							<NButton @click="st.isShow = true" type="info" size="small">{{
+								$t("setting.setting")
+							}}</NButton>
+						</p>
+					</div>
+				</NPopover>
 			</div>
-	
+			<!-- translate-y-[-8px]       -->
 		</div>
 	</div>
 

+ 1 - 1
src/views/mj/aiModel.vue

@@ -52,7 +52,7 @@ const fetchDataGetKnowledge = async () => {
         }));
 
         // 请求成功
-        options.value.push({ label: '暂不配置', value: '' });
+        options.value.push({ label: 'please select', value: '' });
       }
     } catch (error) {
       console.error('Error fetching data:', error);

+ 5 - 2
src/views/mj/aiSider.vue

@@ -133,7 +133,7 @@ const handleSelect = (key: string) => {
 <template>
 
 
-  <!-- <div class="flex-shrink-0 w-[60px] z-[1000]  h-full" v-if="!isMobile" data-tauri-drag-region>
+  <div class="flex-shrink-0 w-[60px] z-[1000]  h-full" v-if="!isMobile" data-tauri-drag-region>
     <div
       class="flex h-full select-none flex-col items-center justify-between bg-[#e8eaf1] px-2 pt-4 pb-8 dark:bg-[#25272d]">
       <div class="flex flex-col space-y-4 flex-1 " data-tauri-drag-region>
@@ -176,6 +176,9 @@ const handleSelect = (key: string) => {
       </div>
 
       <div class="flex flex-col  space-y-2 ">
+        <!-- <NAvatar  v-show="isLogin"  size="large"  round  :src="userInfo.avatar"   v-if="userInfo.avatar"  :fallback-src="defaultAvatar"
+         class=" cursor-pointer"  /> -->
+
         <n-popover trigger="click" :show-arrow="false">
           <template #trigger>
             <n-avatar v-show="isLogin" size="large" round :src="userInfo.avatar" />
@@ -196,6 +199,6 @@ const handleSelect = (key: string) => {
     
   </div>
   <Setting v-if="st.show" v-model:visible="st.show" />
-  <PromptStore v-model:visible="show"></PromptStore> -->
+  <PromptStore v-model:visible="show"></PromptStore>
   
 </template>