feat: add coze assistant
parent
54b35deeab
commit
95252f62f6
|
@ -103,7 +103,7 @@ jobs:
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: pnpm run lint
|
run: pnpm run lint
|
||||||
|
@ -131,7 +131,7 @@ jobs:
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Typecheck
|
- name: Typecheck
|
||||||
run: pnpm check:type
|
run: pnpm check:type
|
||||||
|
|
|
@ -2,6 +2,7 @@ import type { Preferences } from './types';
|
||||||
|
|
||||||
const defaultPreferences: Preferences = {
|
const defaultPreferences: Preferences = {
|
||||||
app: {
|
app: {
|
||||||
|
aiAssistant: true,
|
||||||
authPageLayout: 'panel-right',
|
authPageLayout: 'panel-right',
|
||||||
colorGrayMode: false,
|
colorGrayMode: false,
|
||||||
colorWeakMode: false,
|
colorWeakMode: false,
|
||||||
|
|
|
@ -15,6 +15,8 @@ type PageTransitionType = 'fade' | 'fade-down' | 'fade-slide' | 'fade-up';
|
||||||
type AuthPageLayoutType = 'panel-center' | 'panel-left' | 'panel-right';
|
type AuthPageLayoutType = 'panel-center' | 'panel-left' | 'panel-right';
|
||||||
|
|
||||||
interface AppPreferences {
|
interface AppPreferences {
|
||||||
|
/** 是否开启vben助手 */
|
||||||
|
aiAssistant: boolean;
|
||||||
/** 登录注册页面布局 */
|
/** 登录注册页面布局 */
|
||||||
authPageLayout: AuthPageLayoutType;
|
authPageLayout: AuthPageLayoutType;
|
||||||
/** 是否开启灰色模式 */
|
/** 是否开启灰色模式 */
|
||||||
|
|
|
@ -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>
|
|
@ -0,0 +1 @@
|
||||||
|
export { default as CozeAssistant } from './assistant.vue';
|
|
@ -1,9 +1,16 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { preferences } from '@vben-core/preferences';
|
||||||
import { Toaster } from '@vben-core/shadcn-ui';
|
import { Toaster } from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
|
import { CozeAssistant } from '../coze-assistant';
|
||||||
|
|
||||||
defineOptions({ name: 'GlobalProvider' });
|
defineOptions({ name: 'GlobalProvider' });
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Toaster />
|
<Toaster />
|
||||||
|
<CozeAssistant
|
||||||
|
v-if="preferences.app.aiAssistant"
|
||||||
|
:is-mobile="preferences.app.isMobile"
|
||||||
|
/>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export * from './authentication';
|
export * from './authentication';
|
||||||
|
export * from './coze-assistant';
|
||||||
export * from './fallback';
|
export * from './fallback';
|
||||||
export * from './global-provider';
|
export * from './global-provider';
|
||||||
export * from './global-search';
|
export * from './global-search';
|
||||||
|
|
|
@ -13,6 +13,7 @@ defineOptions({
|
||||||
|
|
||||||
const appLocale = defineModel<string>('appLocale');
|
const appLocale = defineModel<string>('appLocale');
|
||||||
const appDynamicTitle = defineModel<boolean>('appDynamicTitle');
|
const appDynamicTitle = defineModel<boolean>('appDynamicTitle');
|
||||||
|
const appAiAssistant = defineModel<boolean>('appAiAssistant');
|
||||||
|
|
||||||
const localeItems: SelectListItem[] = SUPPORT_LANGUAGES.map((item) => ({
|
const localeItems: SelectListItem[] = SUPPORT_LANGUAGES.map((item) => ({
|
||||||
label: item.text,
|
label: item.text,
|
||||||
|
@ -27,4 +28,7 @@ const localeItems: SelectListItem[] = SUPPORT_LANGUAGES.map((item) => ({
|
||||||
<SwitchItem v-model="appDynamicTitle">
|
<SwitchItem v-model="appDynamicTitle">
|
||||||
{{ $t('preferences.dynamic-title') }}
|
{{ $t('preferences.dynamic-title') }}
|
||||||
</SwitchItem>
|
</SwitchItem>
|
||||||
|
<SwitchItem v-model="appAiAssistant">
|
||||||
|
{{ $t('preferences.ai-assistant') }}
|
||||||
|
</SwitchItem>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -10,6 +10,7 @@ import Preferences from './preferences.vue';
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Preferences
|
<Preferences
|
||||||
|
:app-ai-assistant="preferences.app.aiAssistant"
|
||||||
:app-color-gray-mode="preferences.app.colorGrayMode"
|
:app-color-gray-mode="preferences.app.colorGrayMode"
|
||||||
:app-color-weak-mode="preferences.app.colorWeakMode"
|
:app-color-weak-mode="preferences.app.colorWeakMode"
|
||||||
:app-content-compact="preferences.app.contentCompact"
|
:app-content-compact="preferences.app.contentCompact"
|
||||||
|
@ -46,6 +47,9 @@ import Preferences from './preferences.vue';
|
||||||
:transition-enable="preferences.transition.enable"
|
:transition-enable="preferences.transition.enable"
|
||||||
:transition-name="preferences.transition.name"
|
:transition-name="preferences.transition.name"
|
||||||
:transition-progress="preferences.transition.progress"
|
:transition-progress="preferences.transition.progress"
|
||||||
|
@update:app-ai-assistant="
|
||||||
|
(val) => updatePreferences({ app: { aiAssistant: val } })
|
||||||
|
"
|
||||||
@update:app-color-gray-mode="
|
@update:app-color-gray-mode="
|
||||||
(val) => updatePreferences({ app: { colorGrayMode: val } })
|
(val) => updatePreferences({ app: { colorGrayMode: val } })
|
||||||
"
|
"
|
||||||
|
|
|
@ -58,6 +58,7 @@ withDefaults(defineProps<{ colorPrimaryPresets: string[] }>(), {
|
||||||
const appThemeMode = defineModel<ThemeModeType>('appThemeMode');
|
const appThemeMode = defineModel<ThemeModeType>('appThemeMode');
|
||||||
const appLocale = defineModel<SupportedLanguagesType>('appLocale');
|
const appLocale = defineModel<SupportedLanguagesType>('appLocale');
|
||||||
const appDynamicTitle = defineModel<boolean>('appDynamicTitle');
|
const appDynamicTitle = defineModel<boolean>('appDynamicTitle');
|
||||||
|
const appAiAssistant = defineModel<boolean>('appAiAssistant');
|
||||||
const appLayout = defineModel<LayoutType>('appLayout');
|
const appLayout = defineModel<LayoutType>('appLayout');
|
||||||
const appColorGrayMode = defineModel<boolean>('appColorGrayMode');
|
const appColorGrayMode = defineModel<boolean>('appColorGrayMode');
|
||||||
const appColorWeakMode = defineModel<boolean>('appColorWeakMode');
|
const appColorWeakMode = defineModel<boolean>('appColorWeakMode');
|
||||||
|
@ -172,7 +173,7 @@ function handleReset() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="z-100 fixed right-0 top-2/3">
|
<div class="z-100 fixed right-0 top-1/2">
|
||||||
<VbenSheet
|
<VbenSheet
|
||||||
v-model:open="openPreferences"
|
v-model:open="openPreferences"
|
||||||
:description="$t('preferences.preferences-subtitle')"
|
:description="$t('preferences.preferences-subtitle')"
|
||||||
|
@ -281,6 +282,7 @@ function handleReset() {
|
||||||
<template #general>
|
<template #general>
|
||||||
<Block :title="$t('preferences.general')">
|
<Block :title="$t('preferences.general')">
|
||||||
<General
|
<General
|
||||||
|
v-model:app-ai-assistant="appAiAssistant"
|
||||||
v-model:app-dynamic-title="appDynamicTitle"
|
v-model:app-dynamic-title="appDynamicTitle"
|
||||||
v-model:app-locale="appLocale"
|
v-model:app-locale="appLocale"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -120,6 +120,7 @@ preferences:
|
||||||
preferences: Preferences
|
preferences: Preferences
|
||||||
preferences-subtitle: Customize Preferences & Preview in Real Time
|
preferences-subtitle: Customize Preferences & Preview in Real Time
|
||||||
theme: Theme
|
theme: Theme
|
||||||
|
ai-assistant: Ai Assistant
|
||||||
appearance: Appearance
|
appearance: Appearance
|
||||||
theme-color: Theme Color
|
theme-color: Theme Color
|
||||||
layout: Layout
|
layout: Layout
|
||||||
|
|
|
@ -130,6 +130,7 @@ preferences:
|
||||||
dark-menu: 深色菜单
|
dark-menu: 深色菜单
|
||||||
language: 语言
|
language: 语言
|
||||||
dynamic-title: 动态标题
|
dynamic-title: 动态标题
|
||||||
|
ai-assistant: Ai 助手
|
||||||
collapse: 折叠菜单
|
collapse: 折叠菜单
|
||||||
collapse-show-title: 显示菜单名
|
collapse-show-title: 显示菜单名
|
||||||
wide: 流式
|
wide: 流式
|
||||||
|
|
Loading…
Reference in New Issue