feat: dark mode

This commit is contained in:
Quicy
2026-01-29 14:53:00 +08:00
parent 3ce3be443b
commit 6c3fd23a47
6 changed files with 102 additions and 28 deletions
+23 -3
View File
@@ -4,17 +4,30 @@ import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
DropdownMenuTrigger
} from '@memoh/ui'
import SvgIcon from '@jamescoyle/vue-icon'
import { mdiTranslate } from '@mdi/js'
import { mdiTranslate, mdiBrightness6 } from '@mdi/js'
import { useColorMode } from '@vueuse/core'
const mode = useColorMode()
const modeToggleMap:Record<'dark'|'light','dark'|'light'> = {
dark: 'light',
light:'dark'
}
console.log(mode.value)
const toggleMode = () => {
if (mode.value !== 'auto') {
mode.value = modeToggleMap[mode.value]
}
}
</script>
<template>
<section>
<div
class="fixed top-8 right-2 z-9999 [&:is(:has([data-state=open]))_.translate-icon]:opacity-100"
class="fixed top-0 flex right-8 z-9999 [&:is(:has([data-state=open]))_.translate-icon]:opacity-100 align h-16 items-center"
>
<DropdownMenu>
<DropdownMenuTrigger class="ml-auto mr-4 cursor-pointer">
@@ -33,6 +46,13 @@ import { mdiTranslate } from '@mdi/js'
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<svg-icon
type="mdi"
:path="mdiBrightness6"
class="translate-icon opacity-30 hover:opacity-100 cursor-pointer"
@click="toggleMode"
/>
</div>
<RouterView />
</section>
@@ -1,6 +1,6 @@
<template>
<div class="flex gap-4 items-start">
<div class=" p-2 rounded-full bg-[#F9F9F9]">
<div class=" p-2 rounded-full bg-[#F9F9F9] dark:bg-[#666] ">
<svg-icon
type="mdi"
:path="mdiRobotOutline"
@@ -12,11 +12,59 @@
</sup>
<p class="leading-7 text-muted-foreground break-all">
<template v-if="robotSay.state==='thinking'">
<img
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48Y2lyY2xlIGN4PSI0IiBjeT0iMTIiIHI9IjMiIGZpbGw9ImN1cnJlbnRDb2xvciI+PGFuaW1hdGUgaWQ9IlNWRzlJZ2JSYnNsIiBhdHRyaWJ1dGVOYW1lPSJyIiBiZWdpbj0iMDtTVkdGVU5wQ1dkRy5lbmQtMC4yNXMiIGR1cj0iMC43NXMiIHZhbHVlcz0iMzsuMjszIi8+PC9jaXJjbGU+PGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iMyIgZmlsbD0iY3VycmVudENvbG9yIj48YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJyIiBiZWdpbj0iU1ZHOUlnYlJic2wuZW5kLTAuNnMiIGR1cj0iMC43NXMiIHZhbHVlcz0iMzsuMjszIi8+PC9jaXJjbGU+PGNpcmNsZSBjeD0iMjAiIGN5PSIxMiIgcj0iMyIgZmlsbD0iY3VycmVudENvbG9yIj48YW5pbWF0ZSBpZD0iU1ZHRlVOcENXZEciIGF0dHJpYnV0ZU5hbWU9InIiIGJlZ2luPSJTVkc5SWdiUmJzbC5lbmQtMC40NXMiIGR1cj0iMC43NXMiIHZhbHVlcz0iMzsuMjszIi8+PC9jaXJjbGU+PC9zdmc+"
class="inline"
alt="thinking"
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<circle
cx="4"
cy="12"
r="3"
fill="currentColor"
>
<animate
id="SVG7x14Dcom"
fill="freeze"
attributeName="opacity"
begin="0;SVGqSjG0dUp.end-0.25s"
dur="0.75s"
values="1;0.2"
/>
</circle>
<circle
cx="12"
cy="12"
r="3"
fill="currentColor"
opacity="0.4"
>
<animate
fill="freeze"
attributeName="opacity"
begin="SVG7x14Dcom.begin+0.15s"
dur="0.75s"
values="1;0.2"
/>
</circle>
<circle
cx="20"
cy="12"
r="3"
fill="currentColor"
opacity="0.3"
>
<animate
id="SVGqSjG0dUp"
fill="freeze"
attributeName="opacity"
begin="SVG7x14Dcom.begin+0.3s"
dur="0.75s"
values="1;0.2"
/>
</circle>
</svg>
</template>
<template v-else>
<MarkdownRender
@@ -1,7 +1,7 @@
<template>
<div class="flex">
<p
class="leading-7 not-first:mt-6 max-w-[90%] ml-auto text-muted-foreground bg-[#F9F9F9] p-4 rounded-xl rounded-tr-none break-all
class="leading-7 not-first:mt-6 max-w-[90%] ml-auto text-muted-foreground bg-[#F9F9F9] p-4 rounded-xl rounded-tr-none break-all dark:bg-[#1C1917]
"
>
{{ userSay.description }}
+14 -8
View File
@@ -22,13 +22,14 @@
<script setup lang="ts">
import UserChat from './UserChat/index.vue'
import RobotChat from './RobotChat/index.vue'
import { inject, ref, watch } from 'vue'
import { inject, nextTick, ref, watch } from 'vue'
import { useElementBounding } from '@vueuse/core'
import { useChatList } from '@/store/ChatList'
import { onBeforeRouteLeave } from 'vue-router'
import { storeToRefs } from 'pinia'
// 模拟一下数据
const {chatList,add} = useChatList()
const { loading}=storeToRefs(useChatList())
const chatSay = inject('chatSay', ref(''))
// 模拟一下对话
watch(chatSay, () => {
@@ -80,13 +81,17 @@ watch(height, (newVal,oldVal) => {
}
prevScroll = curScroll
}
if (oldVal === 0 && newVal > container.clientHeight) {
container.scrollTo({
top: cacheScroll,
})
nextTick(() => {
container.scrollTo({
top: cacheScroll,
})
})
return
}
if (!(container && (container?.scrollHeight - container.clientHeight - container.scrollTop) < 1)&&autoScroll) {
if (!(container && (container?.scrollHeight - container.clientHeight - container.scrollTop) < 1) && autoScroll&&loading.value) {
container.scrollTo({
top: container?.scrollHeight - container.clientHeight,
behavior: 'smooth',
@@ -94,12 +99,13 @@ watch(height, (newVal,oldVal) => {
}
})
onBeforeRouteLeave(() => {
const container = displayContainer.value?.parentElement?.parentElement
if (container) {
cacheScroll = container.scrollTop
}
}
})
</script>
@@ -53,15 +53,15 @@ import {
BreadcrumbPage,
BreadcrumbSeparator,
Separator,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
// DropdownMenu,
// DropdownMenuContent,
// DropdownMenuItem,
// DropdownMenuTrigger,
} from '@memoh/ui'
import { useRoute } from 'vue-router'
import { computed } from 'vue'
import SvgIcon from '@jamescoyle/vue-icon'
import { mdiTranslate } from '@mdi/js'
// import SvgIcon from '@jamescoyle/vue-icon'
// import { mdiTranslate } from '@mdi/js'
const route = useRoute()
@@ -98,11 +98,11 @@ const sidebarInfo = computed(() => [
name: 'chat',
icon: mdiChatOutline
},
{
title: t('slidebar.home'),
name: 'home',
icon: mdiHome
},
// {
// title: t('slidebar.home'),
// name: 'home',
// icon: mdiHome
// },
{
title: t('slidebar.model_setting'),
name: 'models',