1
0
forked from Leaf/amber-ui

改进 将 lae 动画复制到 amber

This commit is contained in:
Twilight 2024-09-16 21:31:36 +08:00
parent 0f97ab5bfa
commit 04051f674b
36 changed files with 252 additions and 1 deletions

Binary file not shown.

BIN
src/assets/audios/alert.mp3 Normal file

Binary file not shown.

BIN
src/assets/audios/empty.mp3 Normal file

Binary file not shown.

Binary file not shown.

BIN
src/assets/audios/lock.mp3 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
src/components.d.ts vendored
View File

@ -15,6 +15,7 @@ declare module 'vue' {
ChatSettings: typeof import('./components/settings/ChatSettings.vue')['default']
LeftSettings: typeof import('./components/settings/LeftSettings.vue')['default']
LibrarySettings: typeof import('./components/settings/LibrarySettings.vue')['default']
Lottie: typeof import('./components/Lottie.vue')['default']
MemorySettings: typeof import('./components/settings/MemorySettings.vue')['default']
Menu: typeof import('./components/Menu.vue')['default']
MessageList: typeof import('./components/chat/MessageList.vue')['default']

89
src/components/Lottie.vue Normal file
View File

@ -0,0 +1,89 @@
<template>
<div :id="id" :style="style"></div>
</template>
<script setup lang="ts">
import lottie, { AnimationConfigWithData, AnimationConfigWithPath, AnimationItem } from "lottie-web";
import { onMounted, onUnmounted, ref } from "vue";
const id = ref("lottie-" + Math.random().toString(36).substring(3, 13));
const props = defineProps({
data: {
type: Object,
required: true,
},
autoplay: {
type: Boolean,
default: true,
},
loop: {
type: Boolean,
default: true,
},
height: {
type: Number,
default: 128,
},
width: {
type: Number,
default: 0,
},
center: {
type: Boolean,
default: true,
},
style: {
type: Object,
default: () => {
return {};
},
},
});
const container: Ref<HTMLElement | null> = ref(null);
const animation: Ref<AnimationItem | null> = ref(null);
// const src = "/assets/lottie/" + props.name + ".json";
onMounted(() => {
// get dom
container.value = document.getElementById(id.value);
if (container.value) {
container.value.style.height = props.height + "px";
if (props.width) {
container.value.style.width = props.width + "px";
}
if (props.center) {
container.value.style.textAlign = "center";
}
}
// set height
// if width
// set center(text center)
if (container.value) {
let options: AnimationConfigWithData = {
container: container.value,
renderer: "svg",
loop: props.loop,
autoplay: props.autoplay,
animationData: props.data,
};
animation.value = lottie.loadAnimation(options);
}
});
onUnmounted(() => {
if (animation.value !== null) {
animation.value.destroy();
}
});
</script>

View File

@ -159,6 +159,7 @@ import router from "@/router";
import element from "@/config/element";
import { useIsMobile } from "@/utils/composables";
import { useAppStore } from "@/stores/app";
import { useDialog } from "naive-ui";
// chatId
const chatId: Ref<string | number | undefined | null> = ref(null);
@ -193,7 +194,8 @@ const processing = ref(false);
const fileUpload = ref();
const uploading = ref(false);
const autoScroll = ref(true);
const appStore = useAppStore()
const appStore = useAppStore();
const dialog = useDialog();
function onKeydown(e: KeyboardEvent) {
// shift
@ -473,6 +475,13 @@ function streamChat(streamId: String, redirect = false) {
let append = true;
switch (data.state) {
case "failed":
dialog.error({
title: "推理失败",
content: "目前无法完成推理,请稍后再试。",
positiveText: "好",
});
break;
case "tool_calling":
// toolCalling.value = true;
chatStore.toolName =
@ -500,6 +509,15 @@ function streamChat(streamId: String, redirect = false) {
" 中的 " +
data.tool_call_message.function_name;
dialog.error({
title: "工具调用失败",
content:
data.tool_call_message.tool_name +
" 中的 " +
data.tool_call_message.function_name,
positiveText: "好",
});
// toolError.value = true;
append = false;
setTimeout(() => {

29
src/pages/errors/401.vue Normal file
View File

@ -0,0 +1,29 @@
<template>
<n-result :title="title" description="我们不能验证你的身份。">
<template #icon>
<Lottie :height="250" :data="DizzyFace" />
</template>
</n-result>
</template>
<script setup lang="ts">
import { NResult } from "naive-ui";
import Lottie from "@/components/Lottie.vue";
import { computed } from "vue";
import { useUserStore } from "@/stores/user";
import DizzyFace from "@/assets/lottie/Dizzy-face.json";
const userStore = useUserStore();
const user = computed(() => {
return userStore.user;
});
const title = computed(() => {
if (user.value.name) {
return "你不是 " + user.value.name;
} else {
return "这不是你的账号";
}
});
</script>

36
src/pages/errors/404.vue Normal file
View File

@ -0,0 +1,36 @@
<template>
<n-result
description="我们知道你很急,但是我们确实找不到。"
status="404"
title="资源不存在"
>
<template #icon>
<Lottie :height="250" :data="ThinkingFace" />
</template>
<template v-if="show_footer" #footer>
<n-button @click="goTo('/')">回到首页</n-button>
</template>
</n-result>
</template>
<script setup lang="ts">
import { NButton, NResult } from "naive-ui";
import router from "@/router";
import Lottie from "@/components/Lottie.vue";
import ThinkingFace from "@/assets/lottie/Thinking-face.json";
// import { defineProps } from 'vue'
defineProps({
show_footer: {
type: Boolean,
default: true,
},
});
function goTo(path: any) {
router.push({ name: path });
}
</script>

14
src/pages/errors/500.vue Normal file
View File

@ -0,0 +1,14 @@
<template>
<n-result description="我们的锅" status="500" title="服务器错误">
<template #icon>
<Lottie :height="250" :data="ScrunchedMouth" />
</template>
<template #footer> </template>
</n-result>
</template>
<script setup lang="ts">
import { NResult } from "naive-ui";
import Lottie from "@/components/Lottie.vue";
import ScrunchedMouth from "@/assets/lottie/scrunched-mouth.json";
</script>

View File

@ -0,0 +1,3 @@
<template>
<router-view></router-view>
</template>

View File

@ -2,6 +2,9 @@ import { useUserStore } from "../stores/user";
import { h, computed } from "vue";
import { createDiscreteApi, darkTheme, lightTheme, useOsTheme } from "naive-ui";
import type { ConfigProviderProps } from "naive-ui";
import error401 from "@/pages/errors/401.vue";
import error404 from "@/pages/errors/404.vue";
import error500 from "@/pages/errors/500.vue";
const osThemeRef = useOsTheme();
@ -64,6 +67,40 @@ const response = {
data = error.response.data.error.message;
}
if (error.response.status === 401) {
dialog.error({
title: "401 未授权",
content: () => {
return h(error401, {
show_footer: false,
});
},
});
} else if (error.response.status === 404) {
dialog.error({
title: "404 未找到",
content: () => {
return h(error404, {
show_footer: false,
});
},
});
} else if (error.response.status === 500) {
dialog.error({
title: "500 服务器错误",
content: () => {
return h(error500);
},
});
} else {
if (data.length !== 0) {
dialog.error({
title: "错误",
content: data,
});
}
}
return Promise.reject(error);
},
};

View File

@ -24,6 +24,10 @@ declare module 'vue-router/auto-routes' {
'/auth/login': RouteRecordInfo<'/auth/login', '/auth/login', Record<never, never>, Record<never, never>>,
'/auth/logout': RouteRecordInfo<'/auth/logout', '/auth/logout', Record<never, never>, Record<never, never>>,
'/chat/[id]/': RouteRecordInfo<'/chat/[id]/', '/chat/:id', { id: ParamValue<true> }, { id: ParamValue<false> }>,
'/errors/401': RouteRecordInfo<'/errors/401', '/errors/401', Record<never, never>, Record<never, never>>,
'/errors/404': RouteRecordInfo<'/errors/404', '/errors/404', Record<never, never>, Record<never, never>>,
'/errors/500': RouteRecordInfo<'/errors/500', '/errors/500', Record<never, never>, Record<never, never>>,
'/errors/Base': RouteRecordInfo<'/errors/Base', '/errors/Base', Record<never, never>, Record<never, never>>,
'/guest/': RouteRecordInfo<'/guest/', '/guest', Record<never, never>, Record<never, never>>,
}
}