feat: 引入prettier

This commit is contained in:
2025-06-29 08:32:17 +08:00
parent dfc817e3e3
commit cae0fe371b
29 changed files with 447 additions and 316 deletions

View File

@@ -2,7 +2,12 @@
import type { SelectGroupOption, SelectOption } from "naive-ui";
import { throttle } from "lodash-es";
import AIAvatar from "@/assets/ai_avatar.png";
import { ExclamationTriangleIcon, microphone, PaperAirplaneIcon, TrashIcon } from "@/assets/Icons";
import {
ExclamationTriangleIcon,
microphone,
PaperAirplaneIcon,
TrashIcon
} from "@/assets/Icons";
import UserAvatar from "@/assets/user_avatar.jpg";
import markdown from "@/components/markdown.vue";
import { useAsrStore, useChatStore } from "@/stores";
@@ -10,7 +15,8 @@ import { useAsrStore, useChatStore } from "@/stores";
const chatStore = useChatStore();
const asrStore = useAsrStore();
const { historyMessages, completing, modelList, modelInfo } = storeToRefs(chatStore);
const { historyMessages, completing, modelList, modelInfo } =
storeToRefs(chatStore);
const { isRecording } = storeToRefs(asrStore);
const inputData = ref("");
@@ -22,40 +28,43 @@ const selectedModelId = computed({
get: () => modelInfo.value?.model_id ?? null,
set: (id: string | null) => {
for (const vendor of modelList.value) {
const found = vendor.models.find(model => model.model_id === id);
const found = vendor.models.find((model) => model.model_id === id);
if (found) {
modelInfo.value = found;
return;
}
}
modelInfo.value = null;
},
}
});
// 监听模型列表变化,更新选项
watch(() => modelList.value, (newVal) => {
if (newVal) {
options.value = newVal.map(vendor => ({
type: "group",
label: vendor.vendor,
key: vendor.vendor,
children: vendor.models.map(model => ({
label: model.model_name,
value: model.model_id,
type: model.model_type,
})),
}));
watch(
() => modelList.value,
(newVal) => {
if (newVal) {
options.value = newVal.map((vendor) => ({
type: "group",
label: vendor.vendor,
key: vendor.vendor,
children: vendor.models.map((model) => ({
label: model.model_name,
value: model.model_id,
type: model.model_type
}))
}));
if (newVal.length > 0 && newVal[0].models.length > 0) {
modelInfo.value = newVal[0].models[0];
if (newVal.length > 0 && newVal[0].models.length > 0) {
modelInfo.value = newVal[0].models[0];
}
}
}
}, { immediate: true, deep: true });
},
{ immediate: true, deep: true }
);
// 发送消息
const handleSendMessage = () => {
if (inputData.value.trim() === "")
return;
if (inputData.value.trim() === "") return;
chatStore.addMessageToHistory(inputData.value);
inputData.value = "";
};
@@ -64,8 +73,7 @@ const handleSendMessage = () => {
const toggleRecording = throttle(() => {
if (isRecording.value) {
asrStore.stopRecording();
}
else {
} else {
asrStore.startRecording();
}
}, 500);
@@ -84,7 +92,9 @@ onMounted(() => {
</script>
<template>
<div class="p-8 !pr-4 h-full w-full flex flex-col gap-4 border-l-[24px] border-l-[#FAFAFA] text-base">
<div
class="p-8 !pr-4 h-full w-full flex flex-col gap-4 border-l-[24px] border-l-[#FAFAFA] text-base"
>
<!-- 历史消息区 -->
<NScrollbar ref="scrollbarRef" class="flex-1 pr-4 relative">
<div class="flex items-start mb-4">
@@ -93,20 +103,34 @@ onMounted(() => {
</span>
<div class="text-base w-full max-w-full ml-2 flex flex-col items-start">
<span class="text-base font-bold mb-4">助手</span>
<span class="text-base">你好我是你的智能助手请问有什么可以帮助你的吗</span>
<span class="text-base"
>你好我是你的智能助手请问有什么可以帮助你的吗</span
>
<NDivider />
</div>
</div>
<div v-for="(msg, idx) in historyMessages" :key="idx" class="flex items-start mb-4">
<span v-if="msg.role === 'user'" class="rounded-lg overflow-hidden !w-16 !min-w-16 !h-16">
<div
v-for="(msg, idx) in historyMessages"
:key="idx"
class="flex items-start mb-4"
>
<span
v-if="msg.role === 'user'"
class="rounded-lg overflow-hidden !w-16 !min-w-16 !h-16"
>
<avatar :avatar="UserAvatar" />
</span>
<span v-else class="rounded-lg overflow-hidden">
<avatar :avatar="AIAvatar" />
</span>
<div class="text-base w-full max-w-full ml-2 flex flex-col items-start">
<span class="text-base font-bold">{{ msg.role === 'user' ? '你:' : '助手:' }}</span>
<div v-if="msg.role !== 'user'" class="text-[12px] text-[#7A7A7A] mb-[2px]">
<span class="text-base font-bold">{{
msg.role === "user" ? "你:" : "助手:"
}}</span>
<div
v-if="msg.role !== 'user'"
class="text-[12px] text-[#7A7A7A] mb-[2px]"
>
Tokens: <span class="mr-1">{{ msg.usage?.total_tokens }}</span>
</div>
<div class="w-full max-w-full">
@@ -124,23 +148,34 @@ onMounted(() => {
</NScrollbar>
<!-- 输入框 -->
<NInput
v-model:value="inputData" type="textarea" placeholder="输入内容Enter发送Shift+Enter换行" :autosize="{
v-model:value="inputData"
type="textarea"
placeholder="输入内容Enter发送Shift+Enter换行"
:autosize="{
minRows: 3,
maxRows: 15,
}" @keyup.enter="handleSendMessage"
maxRows: 15
}"
@keyup.enter="handleSendMessage"
/>
<!-- 操作区 -->
<div class="flex justify-between items-center gap-2">
<div class="flex items-center gap-2">
<NSelect
v-model:value="selectedModelId" label-field="label" value-field="value" children-field="children"
filterable :options="options"
v-model:value="selectedModelId"
label-field="label"
value-field="value"
children-field="children"
filterable
:options="options"
/>
</div>
<div class="flex items-center gap-2">
<NPopconfirm
:positive-button-props="{ type: 'error' }" positive-text="清除" negative-text="取消"
@positive-click="chatStore.clearHistoryMessages" @negative-click="() => { }"
:positive-button-props="{ type: 'error' }"
positive-text="清除"
negative-text="取消"
@positive-click="chatStore.clearHistoryMessages"
@negative-click="() => {}"
>
<template #icon>
<ExclamationTriangleIcon class="!w-6 !h-6 text-[#d03050]" />
@@ -158,7 +193,11 @@ onMounted(() => {
{{ isRecording ? "停止输入" : "语音输入" }}
<microphone class="!w-4 !h-4 ml-1" />
</NButton>
<NButton :disabled="isRecording" :loading="completing" @click="handleSendMessage">
<NButton
:disabled="isRecording"
:loading="completing"
@click="handleSendMessage"
>
发送
<PaperAirplaneIcon class="!w-4 !h-4 ml-1" />
</NButton>