Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ declare module 'vue' {
IconMdiLightbulbOutline: typeof import('~icons/mdi/lightbulb-outline')['default']
IconMdiReorderHorizontal: typeof import('~icons/mdi/reorder-horizontal')['default']
IconMdiWeb: typeof import('~icons/mdi/web')['default']
IconRiAddFill: typeof import('~icons/ri/add-fill')['default']
IconRiAlignJustify: typeof import('~icons/ri/align-justify')['default']
IconRiAlignRight: typeof import('~icons/ri/align-right')['default']
IconRiArrowDownSLine: typeof import('~icons/ri/arrow-down-s-line')['default']
Expand All @@ -42,7 +41,6 @@ declare module 'vue' {
IconRiImageEditLine: typeof import('~icons/ri/image-edit-line')['default']
IconRiInboxLine: typeof import('~icons/ri/inbox-line')['default']
IconRiKey2Line: typeof import('~icons/ri/key2-line')['default']
IconRiLink: typeof import('~icons/ri/link')['default']
IconRiListSettingsLine: typeof import('~icons/ri/list-settings-line')['default']
IconRiMailLine: typeof import('~icons/ri/mail-line')['default']
IconRiMessage3Line: typeof import('~icons/ri/message3-line')['default']
Expand All @@ -62,7 +60,6 @@ declare module 'vue' {
NAvatar: typeof import('naive-ui')['NAvatar']
NButton: typeof import('naive-ui')['NButton']
NButtonGroup: typeof import('naive-ui')['NButtonGroup']
NCard: typeof import('naive-ui')['NCard']
NCol: typeof import('naive-ui')['NCol']
NDataTable: typeof import('naive-ui')['NDataTable']
NDatePicker: typeof import('naive-ui')['NDatePicker']
Expand Down
22 changes: 12 additions & 10 deletions src/components/common/UserAvatar/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,29 @@ onMounted(async () => {

<template>
<div class="flex items-center overflow-hidden">
<div class="w-10 h-10 overflow-hidden rounded-full shrink-0">
<div class="w-8 h-8 overflow-hidden rounded-full shrink-0">
<template v-if="isString(userInfo.avatar) && userInfo.avatar.length > 0">
<NAvatar
size="large"
size="medium"
round
:src="userInfo.avatar"
:fallback-src="defaultAvatar"
/>
</template>
<template v-else>
<NAvatar size="large" round :src="defaultAvatar" />
<NAvatar size="medium" round :src="defaultAvatar" />
</template>
</div>
<div class="flex-1 min-w-0 ml-2">
<h2 v-if="userInfo.name" class="">
{{ userInfo.name }}
<NTag v-if="userInfo.roles.length > 0" size="small" :bordered="false" type="success">
{{ UserRole[userInfo.roles[0]] }}
</NTag>
<div class="flex-1 min-w-0 ml-1.5">
<h2 v-if="userInfo.name" class="text-sm leading-tight">
<span class="block">{{ userInfo.name }}</span>
<span v-if="userInfo.roles.length > 0" class="mt-1 inline-flex origin-left scale-90">
<NTag size="tiny" class="text-[4px] leading-none" :bordered="false" type="success">
{{ UserRole[userInfo.roles[0]] }}
</NTag>
</span>
</h2>
<p v-if="userInfo.name" class="overflow-hidden text-xs text-gray-500 text-ellipsis whitespace-nowrap">
<p v-if="userInfo.name" class="overflow-hidden text-[9px] text-gray-500 text-ellipsis whitespace-nowrap">
<span
v-if="isString(userInfo.description) && userInfo.description !== ''"
v-html="userInfo.description"
Expand Down
2 changes: 1 addition & 1 deletion src/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"clickTurnOffThink": "Click to disable deep thinking for this chat.",
"thinkHelp": "After enabling deep thinking, the model will use more computational resources and take longer time to simulate more complex thinking chains for logical reasoning.\nSuitable for complex tasks or high-requirement scenarios, such as mathematical derivations and project planning.\nDaily simple queries do not need to be enabled.",
"showOnContext": "Include context",
"showOffContext": "Not include context",
"showOffContext": "Exclude context",
"maxContextCount": "Maximum number of messages included in the context window",
"searchEnabled": "Search enabled",
"searchDisabled": "Search disabled",
Expand Down
4 changes: 2 additions & 2 deletions src/locales/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@
"clickTurnOnThink": "クリックしてこのチャットで深い思考を有効にします。",
"clickTurnOffThink": "クリックしてこのチャットで深い思考を無効にします。",
"thinkHelp": "深い思考を有効にすると、モデルはより多くの計算資源を使い、複雑な思考連鎖をより長い時間かけてシミュレートします。\n数式導出やプロジェクト計画など、複雑なタスクや高い要件のシナリオに適しています。\n日常的な簡単な問い合わせには不要です。",
"showOnContext": "コンテキストを含める",
"showOffContext": "コンテキストを含めない",
"showOnContext": "コンテキスト含む",
"showOffContext": "コンテキスト除外",
"maxContextCount": "コンテキストウィンドウに含める最大メッセージ数",
"searchEnabled": "検索有効",
"searchDisabled": "検索無効",
Expand Down
39 changes: 1 addition & 38 deletions src/views/chat/components/Header/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,14 @@ defineProps<Props>()

const emit = defineEmits<Emit>()

const { t } = useI18n()

interface Props {
usingContext?: boolean
showPrompt: boolean
searchEnabled?: boolean
thinkEnabled?: boolean
}

interface Emit {
(ev: 'export'): void
(ev: 'toggleUsingContext'): void
(ev: 'toggleShowPrompt'): void
(ev: 'toggleSearchEnabled'): void
(ev: 'toggleThinkEnabled'): void
}

const appStore = useAppStore()
Expand All @@ -44,18 +37,6 @@ function handleExport() {
emit('export')
}

function toggleUsingContext() {
emit('toggleUsingContext')
}

function toggleSearchEnabled() {
emit('toggleSearchEnabled')
}

function toggleThinkEnabled() {
emit('toggleThinkEnabled')
}

function handleShowPrompt() {
emit('toggleShowPrompt')
}
Expand Down Expand Up @@ -83,28 +64,10 @@ function handleShowPrompt() {
</h1>
<div class="flex items-center space-x-2">
<HoverButton @click="handleShowPrompt">
<span class="text-xl" :class="{ 'text-[#4b9e5f]': usingContext, 'text-[#a8071a]': !usingContext }">
<span class="text-xl" :class="{ 'text-[#2f9e44]': usingContext, 'text-[#c92a2a]': !usingContext }">
<IconPrompt class="w-[20px] m-auto" />
</span>
</HoverButton>
<HoverButton :class="{ 'text-[#4b9e5f]': usingContext, 'text-[#a8071a]': !usingContext }" @click="toggleUsingContext">
<span class="text-xl">
<IconRiChatHistoryLine />
</span>
<span style="margin-left:.25em">{{ usingContext ? t('chat.showOnContext') : t('chat.showOffContext') }}</span>
</HoverButton>
<HoverButton :class="{ 'text-[#4b9e5f]': searchEnabled, 'text-[#a8071a]': !searchEnabled }" @click="toggleSearchEnabled">
<span class="text-xl">
<IconMdiWeb />
</span>
<span style="margin-left:.25em">{{ searchEnabled ? t('chat.searchEnabled') : t('chat.searchDisabled') }}</span>
</HoverButton>
<HoverButton :class="{ 'text-[#4b9e5f]': thinkEnabled, 'text-[#a8071a]': !thinkEnabled }" @click="toggleThinkEnabled">
<span class="text-xl">
<IconMdiLightbulbOutline />
</span>
<span style="margin-left:.25em">{{ thinkEnabled ? t('chat.thinkEnabled') : t('chat.thinkDisabled') }}</span>
</HoverButton>
<HoverButton @click="handleExport">
<span class="text-xl text-[#4f555e] dark:text-white">
<IconRiDownload2Line />
Expand Down
75 changes: 53 additions & 22 deletions src/views/chat/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,7 @@ const VALID_IMAGE_TYPES = ['image/png', 'image/jpeg', 'image/webp']
// Paste image.
async function handlePasteImage(event: ClipboardEvent) {
// Check if image upload is enabled.
if (!currentChatRoom.value?.imageUploadEnabled) {
if (currentChatRoom.value?.imageUploadEnabled === false) {
ms.warning(t('chat.imageUploadDisabled') || '图片上传功能已关闭', {
duration: 2000,
})
Expand Down Expand Up @@ -1300,14 +1300,9 @@ onUnmounted(() => {
<div class="flex flex-col w-full h-full">
<HeaderComponent
v-if="isMobile"
:using-context="currentChatRoom?.usingContext"
:show-prompt="showPrompt"
:search-enabled="currentChatRoom?.searchEnabled"
:think-enabled="currentChatRoom?.thinkEnabled"
:using-context="currentChatRoom?.usingContext"
@export="handleExport"
@toggle-using-context="handleToggleUsingContext"
@toggle-search-enabled="handleToggleSearchEnabled"
@toggle-think-enabled="handleToggleThinkEnabled"
@toggle-show-prompt="showPrompt = true"
/>
<main class="flex-1 overflow-hidden">
Expand Down Expand Up @@ -1386,13 +1381,49 @@ onUnmounted(() => {
</NSpace>
</div>

<div class="flex items-center space-x-2">
<div v-if="currentChatRoom?.imageUploadEnabled">
<div
v-if="isMobile"
class="grid grid-cols-3 justify-items-center gap-[clamp(0.125rem,1vw,0.5rem)]"
>
<HoverButton
class="w-full flex justify-center"
:class="{ 'text-[#2f9e44]': currentChatRoom?.searchEnabled, 'text-[#c92a2a]': !currentChatRoom?.searchEnabled }"
@click="handleToggleSearchEnabled"
>
<span class="w-full text-[11px] flex items-center justify-center gap-[clamp(0.125rem,0.6vw,0.375rem)] text-center leading-tight">
<IconMdiWeb class="text-[12px]" />
<span class="text-[11px] font-semibold tracking-tight">{{ currentChatRoom?.searchEnabled ? t('chat.searchEnabled') : t('chat.searchDisabled') }}</span>
</span>
</HoverButton>
<HoverButton
class="w-full flex justify-center"
:class="{ 'text-[#2f9e44]': currentChatRoom?.thinkEnabled, 'text-[#c92a2a]': !currentChatRoom?.thinkEnabled }"
@click="handleToggleThinkEnabled"
>
<span class="w-full text-[11px] flex items-center justify-center gap-[clamp(0.125rem,0.6vw,0.375rem)] text-center leading-tight">
<IconMdiLightbulbOutline class="text-[12px]" />
<span class="text-[11px] font-semibold tracking-tight">{{ currentChatRoom?.thinkEnabled ? t('chat.thinkEnabled') : t('chat.thinkDisabled') }}</span>
</span>
</HoverButton>
<HoverButton
class="w-full flex justify-center"
:class="{ 'text-[#2f9e44]': currentChatRoom?.usingContext, 'text-[#c92a2a]': !currentChatRoom?.usingContext }"
@click="handleToggleUsingContext"
>
<span class="w-full text-[11px] flex items-center justify-center gap-[clamp(0.125rem,0.6vw,0.375rem)] text-center leading-tight">
<IconRiChatHistoryLine class="text-[12px]" />
<span class="text-[11px] font-semibold tracking-tight">{{ currentChatRoom?.usingContext ? t('chat.showOnContext') : t('chat.showOffContext') }}</span>
</span>
</HoverButton>
</div>
<div class="flex items-center" :class="[isMobile ? 'flex-wrap gap-2' : 'space-x-2']">
<div v-if="currentChatRoom">
<NUpload
action="/api/upload-image"
list-type="image"
class="flex items-center justify-center h-10 transition hover:bg-neutral-100 dark:hover:bg-[#414755]"
style="flex-flow:row nowrap;min-width:2.5em;padding:.5em;border-radius:.5em;"
:disabled="currentChatRoom?.imageUploadEnabled === false"
:headers="uploadHeaders"
:show-file-list="false"
:multiple="true"
Expand Down Expand Up @@ -1421,7 +1452,7 @@ onUnmounted(() => {
</span>
</HoverButton>
<NSelect
style="width: 250px"
:style="{ width: isMobile ? '100%' : '250px' }"
:value="currentChatRoom?.chatModel"
:options="chatModelOptions"
:disabled="!!authStore.session?.auth && !authStore.token && !authStore.session?.authProxyEnabled"
Expand All @@ -1432,36 +1463,36 @@ onUnmounted(() => {
v-if="!isMobile"
:tooltip="currentChatRoom?.searchEnabled ? t('chat.clickTurnOffSearch') : t('chat.clickTurnOnSearch')"
:tooltip-help="t('chat.searchHelp')"
:class="{ 'text-[#4b9e5f]': currentChatRoom?.searchEnabled, 'text-[#a8071a]': !currentChatRoom?.searchEnabled }"
:class="{ 'text-[#2f9e44]': currentChatRoom?.searchEnabled, 'text-[#c92a2a]': !currentChatRoom?.searchEnabled }"
@click="handleToggleSearchEnabled"
>
<span class="text-xl flex items-center">
<IconMdiWeb />
<span class="ml-1 text-sm">{{ currentChatRoom?.searchEnabled ? t('chat.searchEnabled') : t('chat.searchDisabled') }}</span>
<span class="text-sm flex items-center gap-1">
<IconMdiWeb class="text-base" />
<span class="text-xs font-bold tracking-wide">{{ currentChatRoom?.searchEnabled ? t('chat.searchEnabled') : t('chat.searchDisabled') }}</span>
</span>
</HoverButton>
<HoverButton
v-if="!isMobile"
:tooltip="currentChatRoom?.thinkEnabled ? t('chat.clickTurnOffThink') : t('chat.clickTurnOnThink')"
:tooltip-help="t('chat.thinkHelp')"
:class="{ 'text-[#4b9e5f]': currentChatRoom?.thinkEnabled, 'text-[#a8071a]': !currentChatRoom?.thinkEnabled }"
:class="{ 'text-[#2f9e44]': currentChatRoom?.thinkEnabled, 'text-[#c92a2a]': !currentChatRoom?.thinkEnabled }"
@click="handleToggleThinkEnabled"
>
<span class="text-xl flex items-center">
<IconMdiLightbulbOutline />
<span class="ml-1 text-sm">{{ currentChatRoom?.thinkEnabled ? t('chat.thinkEnabled') : t('chat.thinkDisabled') }}</span>
<span class="text-sm flex items-center gap-1">
<IconMdiLightbulbOutline class="text-base" />
<span class="text-xs font-bold tracking-wide">{{ currentChatRoom?.thinkEnabled ? t('chat.thinkEnabled') : t('chat.thinkDisabled') }}</span>
</span>
</HoverButton>
<HoverButton
v-if="!isMobile"
:tooltip="currentChatRoom?.usingContext ? t('chat.clickTurnOffContext') : t('chat.clickTurnOnContext')"
:tooltip-help="t('chat.contextHelp')"
:class="{ 'text-[#4b9e5f]': currentChatRoom?.usingContext, 'text-[#a8071a]': !currentChatRoom?.usingContext }"
:class="{ 'text-[#2f9e44]': currentChatRoom?.usingContext, 'text-[#c92a2a]': !currentChatRoom?.usingContext }"
@click="handleToggleUsingContext"
>
<span class="text-xl flex items-center">
<IconRiChatHistoryLine />
<span class="ml-1 text-sm">{{ currentChatRoom?.usingContext ? t('chat.showOnContext') : t('chat.showOffContext') }}</span>
<span class="text-sm flex items-center gap-1">
<IconRiChatHistoryLine class="text-base" />
<span class="text-xs font-bold tracking-wide">{{ currentChatRoom?.usingContext ? t('chat.showOnContext') : t('chat.showOffContext') }}</span>
</span>
</HoverButton>
<NSlider
Expand Down
8 changes: 4 additions & 4 deletions src/views/chat/layout/sider/Footer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ async function handleLogout() {
<div class="flex-1 shrink-0 overflow-hidden">
<UserAvatar />
</div>
<HoverButton v-if="!!authStore.token || !!authStore.session?.authProxyEnabled" :tooltip="t('common.logOut')" @click="handleLogout">
<span class="text-xl text-[#4f555e] dark:text-white">
<HoverButton v-if="!!authStore.token || !!authStore.session?.authProxyEnabled" class="-mr-1" :tooltip="t('common.logOut')" @click="handleLogout">
<span class="text-lg font-semibold text-[#4f555e] dark:text-white">
<IconUilExit />
</span>
</HoverButton>

<HoverButton v-if="!!authStore.token || !!authStore.session?.authProxyEnabled" :tooltip="t('setting.setting')" @click="show = true">
<span class="text-xl text-[#4f555e] dark:text-white">
<HoverButton v-if="!!authStore.token || !!authStore.session?.authProxyEnabled" class="ml-0.5" :tooltip="t('setting.setting')" @click="show = true">
<span class="text-lg font-semibold text-[#4f555e] dark:text-white">
<IconRiSettings4Line />
</span>
</HoverButton>
Expand Down