feat: add coze assistant

pull/48/MERGE
vben 2024-06-16 23:17:40 +08:00
parent 54b35deeab
commit 95252f62f6
12 changed files with 97 additions and 3 deletions

View File

@ -103,7 +103,7 @@ jobs:
cache: "pnpm"
- name: Install dependencies
run: pnpm install
run: pnpm install --frozen-lockfile
- name: Lint
run: pnpm run lint
@ -131,7 +131,7 @@ jobs:
cache: "pnpm"
- name: Install dependencies
run: pnpm install
run: pnpm install --frozen-lockfile
- name: Typecheck
run: pnpm check:type

View File

@ -2,6 +2,7 @@ import type { Preferences } from './types';
const defaultPreferences: Preferences = {
app: {
aiAssistant: true,
authPageLayout: 'panel-right',
colorGrayMode: false,
colorWeakMode: false,

View File

@ -15,6 +15,8 @@ type PageTransitionType = 'fade' | 'fade-down' | 'fade-slide' | 'fade-up';
type AuthPageLayoutType = 'panel-center' | 'panel-left' | 'panel-right';
interface AppPreferences {
/** 是否开启vben助手 */
aiAssistant: boolean;
/** 登录注册页面布局 */
authPageLayout: AuthPageLayoutType;
/** 是否开启灰色模式 */

View File

@ -0,0 +1,70 @@
<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';
import { useScriptTag } from '@vueuse/core';
interface AssistantProps {
botIcon?: string;
botId?: string;
botTitle?: string;
isMobile?: boolean;
}
const props = withDefaults(defineProps<AssistantProps>(), {
botIcon:
'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.3/source/avatar-v1-transparent-bg.webp',
botId: '7374674983739621392',
botTitle: 'Vben Admin Assistant',
isMobile: false,
});
let client: any;
const wrapperEl = ref();
const { load, unload } = useScriptTag(
'https://sf-cdn.coze.com/obj/unpkg-va/flow-platform/chat-app-sdk/0.1.0-beta.4/libs/oversea/index.js',
() => {
client = new (window as any).CozeWebSDK.WebChatClient({
componentProps: {
icon: props.botIcon,
layout: props.isMobile ? 'mobile' : 'pc',
// lang: 'zh-CN',
title: props.botTitle,
},
config: {
bot_id: props.botId,
},
el: wrapperEl.value,
});
},
{
manual: true,
},
);
onMounted(() => {
load();
});
onUnmounted(() => {
unload();
client?.destroy();
});
</script>
<template>
<div ref="wrapperEl" class="coze-assistant"></div>
</template>
<style>
.coze-assistant {
position: absolute;
right: 30px;
bottom: 30px;
z-index: 1000;
img {
width: 42px !important;
height: 42px !important;
border-radius: 50%;
}
}
</style>

View File

@ -0,0 +1 @@
export { default as CozeAssistant } from './assistant.vue';

View File

@ -1,9 +1,16 @@
<script setup lang="ts">
import { preferences } from '@vben-core/preferences';
import { Toaster } from '@vben-core/shadcn-ui';
import { CozeAssistant } from '../coze-assistant';
defineOptions({ name: 'GlobalProvider' });
</script>
<template>
<Toaster />
<CozeAssistant
v-if="preferences.app.aiAssistant"
:is-mobile="preferences.app.isMobile"
/>
<slot></slot>
</template>

View File

@ -1,4 +1,5 @@
export * from './authentication';
export * from './coze-assistant';
export * from './fallback';
export * from './global-provider';
export * from './global-search';

View File

@ -13,6 +13,7 @@ defineOptions({
const appLocale = defineModel<string>('appLocale');
const appDynamicTitle = defineModel<boolean>('appDynamicTitle');
const appAiAssistant = defineModel<boolean>('appAiAssistant');
const localeItems: SelectListItem[] = SUPPORT_LANGUAGES.map((item) => ({
label: item.text,
@ -27,4 +28,7 @@ const localeItems: SelectListItem[] = SUPPORT_LANGUAGES.map((item) => ({
<SwitchItem v-model="appDynamicTitle">
{{ $t('preferences.dynamic-title') }}
</SwitchItem>
<SwitchItem v-model="appAiAssistant">
{{ $t('preferences.ai-assistant') }}
</SwitchItem>
</template>

View File

@ -10,6 +10,7 @@ import Preferences from './preferences.vue';
</script>
<template>
<Preferences
:app-ai-assistant="preferences.app.aiAssistant"
:app-color-gray-mode="preferences.app.colorGrayMode"
:app-color-weak-mode="preferences.app.colorWeakMode"
:app-content-compact="preferences.app.contentCompact"
@ -46,6 +47,9 @@ import Preferences from './preferences.vue';
:transition-enable="preferences.transition.enable"
:transition-name="preferences.transition.name"
:transition-progress="preferences.transition.progress"
@update:app-ai-assistant="
(val) => updatePreferences({ app: { aiAssistant: val } })
"
@update:app-color-gray-mode="
(val) => updatePreferences({ app: { colorGrayMode: val } })
"

View File

@ -58,6 +58,7 @@ withDefaults(defineProps<{ colorPrimaryPresets: string[] }>(), {
const appThemeMode = defineModel<ThemeModeType>('appThemeMode');
const appLocale = defineModel<SupportedLanguagesType>('appLocale');
const appDynamicTitle = defineModel<boolean>('appDynamicTitle');
const appAiAssistant = defineModel<boolean>('appAiAssistant');
const appLayout = defineModel<LayoutType>('appLayout');
const appColorGrayMode = defineModel<boolean>('appColorGrayMode');
const appColorWeakMode = defineModel<boolean>('appColorWeakMode');
@ -172,7 +173,7 @@ function handleReset() {
</script>
<template>
<div class="z-100 fixed right-0 top-2/3">
<div class="z-100 fixed right-0 top-1/2">
<VbenSheet
v-model:open="openPreferences"
:description="$t('preferences.preferences-subtitle')"
@ -281,6 +282,7 @@ function handleReset() {
<template #general>
<Block :title="$t('preferences.general')">
<General
v-model:app-ai-assistant="appAiAssistant"
v-model:app-dynamic-title="appDynamicTitle"
v-model:app-locale="appLocale"
/>

View File

@ -120,6 +120,7 @@ preferences:
preferences: Preferences
preferences-subtitle: Customize Preferences & Preview in Real Time
theme: Theme
ai-assistant: Ai Assistant
appearance: Appearance
theme-color: Theme Color
layout: Layout

View File

@ -130,6 +130,7 @@ preferences:
dark-menu: 深色菜单
language: 语言
dynamic-title: 动态标题
ai-assistant: Ai 助手
collapse: 折叠菜单
collapse-show-title: 显示菜单名
wide: 流式