@vyr/service-chat 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +18 -0
- package/src/ChatService.ts +104 -0
- package/src/chat/ChatHistory.ts +127 -0
- package/src/chat/ChatSession.ts +183 -0
- package/src/chat/ChatWindow.ts +92 -0
- package/src/chat/ChatWindowManager.ts +72 -0
- package/src/chat/index.ts +4 -0
- package/src/common/Draggable.ts +36 -0
- package/src/common/index.ts +1 -0
- package/src/components/ChatAgent.vue +44 -0
- package/src/components/ChatExecutor.vue +85 -0
- package/src/components/ChatProcess.vue +144 -0
- package/src/components/ChatView.vue +135 -0
- package/src/components/ChatWindow.vue +64 -0
- package/src/components/Input.vue +170 -0
- package/src/components/Welcome.vue +56 -0
- package/src/components/executor/ExecutorHeader.vue +72 -0
- package/src/components/executor/GearLoading.vue +104 -0
- package/src/components/executor/ParamSection.vue +243 -0
- package/src/components/executor/ToolItem.vue +262 -0
- package/src/components/executor/types.ts +27 -0
- package/src/components/executor/useExecutor.ts +117 -0
- package/src/components/index.ts +11 -0
- package/src/executor/index.ts +17 -0
- package/src/index.ts +10 -0
- package/src/locale/Language.ts +10 -0
- package/src/locale/LanguageProvider.ts +49 -0
- package/src/locale/index.ts +2 -0
- package/tsconfig.json +37 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="tasks.length" class="chat-executor">
|
|
3
|
+
<ExecutorHeader :title="title" :spinning="hasRunningTask" :completed="completedCount" :total="totalCount" />
|
|
4
|
+
|
|
5
|
+
<div class="tools-list">
|
|
6
|
+
<ToolItem v-for="task in tasks" :key="task.toolCallId" :task="task" :expanded="isTaskExpanded(task.toolCallId)"
|
|
7
|
+
@toggle="handleToggle" @copy="handleCopy" />
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup lang="ts">
|
|
13
|
+
import { computed } from 'vue';
|
|
14
|
+
import { language } from '../locale'
|
|
15
|
+
import { useExecutor } from './executor/useExecutor'
|
|
16
|
+
import { ExecutorProps, ExecutorEmits, ParamSectionType } from './executor/types'
|
|
17
|
+
import ExecutorHeader from './executor/ExecutorHeader.vue'
|
|
18
|
+
import ToolItem from './executor/ToolItem.vue'
|
|
19
|
+
|
|
20
|
+
const props = withDefaults(defineProps<ExecutorProps>(), {
|
|
21
|
+
tasks: () => [],
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const title = computed(() => {
|
|
25
|
+
return completedCount.value === totalCount.value ? language.get('executor.task.execution.record') : language.get('executor.task.status.running')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const emit = defineEmits<ExecutorEmits>()
|
|
29
|
+
|
|
30
|
+
const {
|
|
31
|
+
hasRunningTask,
|
|
32
|
+
completedCount,
|
|
33
|
+
totalCount,
|
|
34
|
+
expandedTasks,
|
|
35
|
+
toggleTask,
|
|
36
|
+
isTaskExpanded,
|
|
37
|
+
copyToClipboard,
|
|
38
|
+
formatJSON
|
|
39
|
+
} = useExecutor(props)
|
|
40
|
+
|
|
41
|
+
// 处理任务展开/折叠
|
|
42
|
+
const handleToggle = (taskId: string | number) => {
|
|
43
|
+
toggleTask(taskId)
|
|
44
|
+
emit('task:toggle', taskId, expandedTasks.value[taskId])
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 处理复制
|
|
48
|
+
const handleCopy = async (type: string, taskId: string | number) => {
|
|
49
|
+
const task = props.tasks.find(t => t.toolCallId === taskId)
|
|
50
|
+
if (!task) return
|
|
51
|
+
|
|
52
|
+
let content: any
|
|
53
|
+
if (type === 'input') {
|
|
54
|
+
content = task.args
|
|
55
|
+
} else if (type === 'output') {
|
|
56
|
+
content = task.result
|
|
57
|
+
} else if (type === 'error') {
|
|
58
|
+
content = task.result
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!content) return
|
|
62
|
+
|
|
63
|
+
const text = formatJSON(content)
|
|
64
|
+
await copyToClipboard(text, type as ParamSectionType, taskId, emit)
|
|
65
|
+
}
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<style scoped>
|
|
69
|
+
.chat-executor {
|
|
70
|
+
background: #252526;
|
|
71
|
+
border-radius: 20px;
|
|
72
|
+
margin: 16px 0;
|
|
73
|
+
padding: 24px;
|
|
74
|
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
|
|
75
|
+
width: 100%;
|
|
76
|
+
border: 1px solid #3c3c3d;
|
|
77
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.tools-list {
|
|
81
|
+
display: flex;
|
|
82
|
+
flex-direction: column;
|
|
83
|
+
gap: 12px;
|
|
84
|
+
}
|
|
85
|
+
</style>
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<vyr-scroll ref="scrollRef" :padding="10" :margin="10" @wheel="onWheel">
|
|
3
|
+
<div class='chat-list'>
|
|
4
|
+
<template v-for="(msg, idx) in chatService.manager.window.history.list" :key="idx">
|
|
5
|
+
<McBubble v-if="msg.role === 'user'" :content="getTextContent(msg)" :align="'right'"
|
|
6
|
+
:avatarConfig="getAvatarConfig(msg)">
|
|
7
|
+
<template #bottom>
|
|
8
|
+
<div class="bubble-bottom-operations" v-if="msg.complete">
|
|
9
|
+
<McCopyIcon :text="getTextContent(msg)" class="copy-class" />
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
</McBubble>
|
|
13
|
+
<McBubble v-else :loading="msg.loading" :avatarConfig="getAvatarConfig(msg)" :data-v-idx="idx">
|
|
14
|
+
<template v-for="(chunk, i) in msg.chunks" :key="i">
|
|
15
|
+
<ChatExecutor v-if="chunk.type === 'tool'" :tasks="getTasks(chunk)"></ChatExecutor>
|
|
16
|
+
<McMarkdownCard v-else :content="getRenderContent(chunk)" :theme="themeService.currentTheme"
|
|
17
|
+
:enableThink="true" :mdPlugins="mdPlugins" :enableMermaid="true" />
|
|
18
|
+
</template>
|
|
19
|
+
<template #bottom>
|
|
20
|
+
<div class="bubble-bottom-operations" v-if="msg.complete">
|
|
21
|
+
<McCopyIcon :text="getTextContent(msg)" class="copy-class" />
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
</McBubble>
|
|
25
|
+
</template>
|
|
26
|
+
</div>
|
|
27
|
+
</vyr-scroll>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script setup lang="ts">
|
|
31
|
+
import { nextTick, ref, useTemplateRef, watch } from 'vue';
|
|
32
|
+
import { runtime } from '@vyr/runtime';
|
|
33
|
+
import { themeService, VyrScroll } from '@vyr/design'
|
|
34
|
+
import { McBubble, McMarkdownCard, McCopyIcon } from '@matechat/core';
|
|
35
|
+
import { katex } from '@mdit/plugin-katex';
|
|
36
|
+
import { ChatMessage, ChatMessageChunk, ChatMessageToolChunk } from '../chat';
|
|
37
|
+
import { ChatService } from "../ChatService";
|
|
38
|
+
import ChatExecutor from './ChatExecutor.vue';
|
|
39
|
+
|
|
40
|
+
const chatService = runtime.get<ChatService>('chat')
|
|
41
|
+
const avatarSize = ref(36)
|
|
42
|
+
const wheelHadUp = ref(false);
|
|
43
|
+
const mdPlugins = ref([
|
|
44
|
+
{ plugin: katex, opt: {} },
|
|
45
|
+
])
|
|
46
|
+
|
|
47
|
+
const getTasks = (chunk: ChatMessageToolChunk) => {
|
|
48
|
+
const toolNames = [...chunk.collection.values()]
|
|
49
|
+
return toolNames
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const getAvatarConfig = (msg: ChatMessage) => {
|
|
53
|
+
return {
|
|
54
|
+
imgSrc: msg.avatarConfig,
|
|
55
|
+
width: avatarSize.value,
|
|
56
|
+
height: avatarSize.value
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const getTextContent = (msg: ChatMessage) => {
|
|
61
|
+
let content = ''
|
|
62
|
+
for (const chunk of msg.chunks) {
|
|
63
|
+
if (chunk.type === 'text') content += chunk.content
|
|
64
|
+
}
|
|
65
|
+
return content
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const getRenderContent = (chunk: ChatMessageChunk) => {
|
|
69
|
+
if (chunk.type === 'text') {
|
|
70
|
+
return chunk.content
|
|
71
|
+
} else if (chunk.type === 'reasoning') {
|
|
72
|
+
return `<think>${chunk.content}</think>`
|
|
73
|
+
}
|
|
74
|
+
// else {
|
|
75
|
+
// let displayContent = `\n\n**🟡 ${chunk.toolName}**\n`;
|
|
76
|
+
// displayContent += `\n**${language.get('chat.process.tool.call.args')}**\n\`\`\`json\n${JSON.stringify(chunk.args, null, 2)}\n\`\`\`\n`;
|
|
77
|
+
// displayContent += `\n**${language.get('chat.process.tool.call.result')}**\n\`\`\`json\n${JSON.stringify(chunk.result, null, 2)}\n\`\`\`\n`;
|
|
78
|
+
|
|
79
|
+
// return displayContent
|
|
80
|
+
// }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const onWheel = (e: WheelEvent) => {
|
|
84
|
+
const wrapper = scrollRef?.value?.wrapper;
|
|
85
|
+
if (wrapper) {
|
|
86
|
+
wheelHadUp.value = e.deltaY < 0;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const scrollRef = useTemplateRef('scrollRef')
|
|
91
|
+
const nextTo = () => {
|
|
92
|
+
if (wheelHadUp.value) return
|
|
93
|
+
const wrapper = scrollRef?.value?.wrapper;
|
|
94
|
+
if (!wrapper) return
|
|
95
|
+
wrapper.scrollTo({
|
|
96
|
+
top: wrapper.scrollHeight,
|
|
97
|
+
behavior: 'smooth',
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
const scrollTo = () => nextTick(nextTo)
|
|
101
|
+
watch(() => chatService.manager.window.history.lastMessage.current, scrollTo, { deep: true })
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
<style scoped lang="scss">
|
|
105
|
+
@import "devui-theme/styles-var/devui-var.scss";
|
|
106
|
+
@import 'katex/dist/katex.min.css';
|
|
107
|
+
|
|
108
|
+
:deep(.mc-bubble-content-container) {
|
|
109
|
+
max-width: calc(100% - 78px) !important;
|
|
110
|
+
|
|
111
|
+
.mc-markdown-render {
|
|
112
|
+
overflow: hidden;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
:deep(.mc-bubble-right) {
|
|
117
|
+
.bubble-bottom-operations {
|
|
118
|
+
text-align: right;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.tool-runing {
|
|
123
|
+
width: 100%;
|
|
124
|
+
height: 1.5em;
|
|
125
|
+
line-height: 1.5em;
|
|
126
|
+
display: flex;
|
|
127
|
+
align-items: center;
|
|
128
|
+
|
|
129
|
+
.tool-loading {
|
|
130
|
+
margin-left: 4px;
|
|
131
|
+
animation: loading-rotate 1.5s infinite;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@keyframes loading-rotate {
|
|
136
|
+
0% {
|
|
137
|
+
transform: rotate(0);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
100% {
|
|
141
|
+
transform: rotate(360deg);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
</style>
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="chat-view-wrapper" @mousedown="unactive">
|
|
3
|
+
<div class="chat-view-container">
|
|
4
|
+
<Welcome v-if="chatService.manager.window.history.list.length === 0" />
|
|
5
|
+
<ChatProcess class="chat-message" v-else />
|
|
6
|
+
<div class="new-convo-button">
|
|
7
|
+
<div class="agent-knowledge">
|
|
8
|
+
<ChatWindow class="chat-item" />
|
|
9
|
+
<span class="agent-knowledge-dividing-line"></span>
|
|
10
|
+
<ChatAgent class="chat-item" />
|
|
11
|
+
</div>
|
|
12
|
+
<div class="new-chat-btn" @click="addWindow">
|
|
13
|
+
<i class="vyrfont vyr-add"></i>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
<Input />
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script setup lang="ts">
|
|
22
|
+
import { runtime, ShortcutkeyService } from "@vyr/runtime";
|
|
23
|
+
import { ChatService } from "../ChatService";
|
|
24
|
+
import ChatProcess from "./ChatProcess.vue";
|
|
25
|
+
import Input from "./Input.vue";
|
|
26
|
+
import Welcome from "./Welcome.vue";
|
|
27
|
+
import ChatAgent from './ChatAgent.vue'
|
|
28
|
+
import ChatWindow from './ChatWindow.vue'
|
|
29
|
+
|
|
30
|
+
const chatService = runtime.get<ChatService>('chat')
|
|
31
|
+
const shortcutkeyService = runtime.get<ShortcutkeyService>('shortcutkey')
|
|
32
|
+
|
|
33
|
+
const unactive = () => {
|
|
34
|
+
shortcutkeyService.unactive()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const addWindow = () => {
|
|
38
|
+
if (chatService.manager.isPendingWindow()) return
|
|
39
|
+
const window = chatService.manager.createWindow({ agentId: chatService.getDefaultAgentId() })
|
|
40
|
+
chatService.manager.setCurrentWindow(window)
|
|
41
|
+
}
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<style scoped lang="scss">
|
|
45
|
+
@import "devui-theme/styles-var/devui-var.scss";
|
|
46
|
+
|
|
47
|
+
.chat-view-wrapper {
|
|
48
|
+
width: 100%;
|
|
49
|
+
height: 100%;
|
|
50
|
+
position: relative;
|
|
51
|
+
display: flex;
|
|
52
|
+
color: #fff;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.chat-view-container {
|
|
56
|
+
width: 100%;
|
|
57
|
+
height: 100%;
|
|
58
|
+
display: flex;
|
|
59
|
+
flex-direction: column;
|
|
60
|
+
align-items: center;
|
|
61
|
+
gap: 8px;
|
|
62
|
+
|
|
63
|
+
.chat-message {
|
|
64
|
+
flex: 1;
|
|
65
|
+
display: flex;
|
|
66
|
+
flex-direction: column;
|
|
67
|
+
overflow: auto;
|
|
68
|
+
width: 100%;
|
|
69
|
+
padding-top: 20px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.chat-item {
|
|
73
|
+
border-radius: $devui-border-radius-full;
|
|
74
|
+
|
|
75
|
+
:deep(.vyr-dropdown-trigger) {
|
|
76
|
+
padding: 0 8px 0 4px;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.new-convo-button {
|
|
81
|
+
box-sizing: border-box;
|
|
82
|
+
padding: 0 12px;
|
|
83
|
+
display: flex;
|
|
84
|
+
justify-content: flex-end;
|
|
85
|
+
align-items: center;
|
|
86
|
+
width: 100%;
|
|
87
|
+
max-width: 1200px;
|
|
88
|
+
height: 39px;
|
|
89
|
+
gap: 4px;
|
|
90
|
+
|
|
91
|
+
.agent-knowledge {
|
|
92
|
+
flex: 1;
|
|
93
|
+
display: flex;
|
|
94
|
+
align-items: center;
|
|
95
|
+
|
|
96
|
+
.agent-knowledge-dividing-line {
|
|
97
|
+
width: 1px;
|
|
98
|
+
height: 14px;
|
|
99
|
+
margin: 0 12px;
|
|
100
|
+
background-color: $devui-line;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.new-chat-btn {
|
|
106
|
+
display: flex;
|
|
107
|
+
justify-content: center;
|
|
108
|
+
align-items: center;
|
|
109
|
+
width: 24px;
|
|
110
|
+
height: 24px;
|
|
111
|
+
border-radius: $devui-border-radius-full;
|
|
112
|
+
background-color: $devui-base-bg;
|
|
113
|
+
box-shadow: 0px 1px 8px 0px rgba(25, 25, 25, 0.06);
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
|
|
116
|
+
&:hover {
|
|
117
|
+
color: $devui-brand;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
body[ui-theme-type="light"] {
|
|
123
|
+
.chat-view-wrapper {
|
|
124
|
+
background: linear-gradient(180deg,
|
|
125
|
+
rgba(255, 255, 255, 0.95),
|
|
126
|
+
rgba(248, 250, 255, 0.95) 99%);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
body[ui-theme-type="dark"] {
|
|
131
|
+
.chat-view-wrapper {
|
|
132
|
+
background-color: $devui-global-bg;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
</style>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<vyr-dropdown class="window-wrapper" :model-value="chatService.manager.window.threadId" :data="windows"
|
|
3
|
+
:removable="true" @change="changeWindow" @remove="deleteWindow">
|
|
4
|
+
<template #default>
|
|
5
|
+
<div class="window">{{ chatService.manager.window.threadId }}</div>
|
|
6
|
+
</template>
|
|
7
|
+
</vyr-dropdown>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup lang="ts">
|
|
11
|
+
import { computed } from 'vue';
|
|
12
|
+
import { runtime } from '@vyr/runtime';
|
|
13
|
+
import { Option, VyrDropdown } from '@vyr/design';
|
|
14
|
+
import { ChatService } from '../ChatService';
|
|
15
|
+
|
|
16
|
+
const chatService = runtime.get<ChatService>('chat')
|
|
17
|
+
|
|
18
|
+
const windows = computed(() => {
|
|
19
|
+
const items = chatService.manager.getWindows()
|
|
20
|
+
const windows: Option[] = []
|
|
21
|
+
for (const item of items) {
|
|
22
|
+
windows.push({ label: item.threadId, value: item.threadId })
|
|
23
|
+
}
|
|
24
|
+
return windows
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const deleteWindow = async (index: number) => {
|
|
28
|
+
if (windows.value.length === 1) return
|
|
29
|
+
const item = windows.value[index]
|
|
30
|
+
const window = chatService.manager.getWindow(item.value)
|
|
31
|
+
if (window === null) return
|
|
32
|
+
await chatService.manager.deleteWindow(window)
|
|
33
|
+
if (chatService.manager.window === window) {
|
|
34
|
+
const current = chatService.manager.getWindows()[0]
|
|
35
|
+
chatService.manager.setCurrentWindow(current)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const changeWindow = (id: string) => {
|
|
39
|
+
const window = chatService.manager.getWindow(id)
|
|
40
|
+
if (window === null) return
|
|
41
|
+
chatService.manager.setCurrentWindow(window)
|
|
42
|
+
}
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<style scoped lang="scss">
|
|
46
|
+
@import "devui-theme/styles-var/devui-var.scss";
|
|
47
|
+
|
|
48
|
+
$item-height: 24px;
|
|
49
|
+
|
|
50
|
+
.window-wrapper {
|
|
51
|
+
width: 140px;
|
|
52
|
+
background-color: $devui-base-bg;
|
|
53
|
+
box-shadow: 0px 1px 8px 0px rgba(25, 25, 25, 0.06);
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
|
|
56
|
+
.window {
|
|
57
|
+
overflow: hidden;
|
|
58
|
+
height: $item-height;
|
|
59
|
+
line-height: $item-height;
|
|
60
|
+
padding: 0 0 0 8px;
|
|
61
|
+
box-sizing: border-box;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
</style>
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="input-container">
|
|
3
|
+
<McInput :value="chatService.manager.window.question" :maxLength="chatService.manager.window.maxLength"
|
|
4
|
+
:variant="BorderLess" :loading="chatService.manager.window.runing" :disabled="chatService.manager.window.disbaled"
|
|
5
|
+
:placeholder="language.get('chat.input.placeholder')" @change="updateQuestion" @submit="onSubmit"
|
|
6
|
+
@mouseenter="mouseenter" @mouseup="mouseup" @cancel="onCancel">
|
|
7
|
+
<template #extra>
|
|
8
|
+
<div class="input-foot-wrapper">
|
|
9
|
+
<span class="input-foot-maxlength">
|
|
10
|
+
{{ chatService.manager.window.question.length }}/{{ chatService.manager.window.maxLength }}
|
|
11
|
+
</span>
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
14
|
+
</McInput>
|
|
15
|
+
</div>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script setup lang="ts">
|
|
19
|
+
import { McInput } from '@matechat/core';
|
|
20
|
+
import { DataService, DraggableService, runtime } from '@vyr/runtime';
|
|
21
|
+
import { DraggableController } from '@vyr/design';
|
|
22
|
+
import { language } from '../locale';
|
|
23
|
+
import { ChatSession } from '../chat';
|
|
24
|
+
import { ChatService } from '../ChatService';
|
|
25
|
+
|
|
26
|
+
const dataService = runtime.get<DataService>('data')
|
|
27
|
+
const chatService = runtime.get<ChatService>('chat')
|
|
28
|
+
const BorderLess: any = 'borderless'
|
|
29
|
+
|
|
30
|
+
const updateQuestion = (value: string) => {
|
|
31
|
+
chatService.manager.window.question = value
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let result: ChatSession | null = null
|
|
35
|
+
|
|
36
|
+
const onSubmit = async () => {
|
|
37
|
+
if (chatService.manager.window.runing) return
|
|
38
|
+
chatService.manager.window.runing = true
|
|
39
|
+
try {
|
|
40
|
+
result = await chatService.manager.window.ask(chatService.manager.window.question)
|
|
41
|
+
await result.done()
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error(error)
|
|
44
|
+
} finally {
|
|
45
|
+
chatService.manager.window.runing = false
|
|
46
|
+
result = null
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const onCancel = async () => {
|
|
51
|
+
if (result === null) return
|
|
52
|
+
try {
|
|
53
|
+
chatService.manager.window.disbaled = true
|
|
54
|
+
await result.stop()
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.log(error)
|
|
57
|
+
} finally {
|
|
58
|
+
chatService.manager.window.disbaled = false
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const draggableService = runtime.get<DraggableService>('draggable')
|
|
63
|
+
const draggable = draggableService.get(DraggableService.key.chat)
|
|
64
|
+
const mouseenter = (e: MouseEvent) => {
|
|
65
|
+
if (DraggableController.enabled === false) return
|
|
66
|
+
DraggableController.enter({ key: '', value: null }, draggable)
|
|
67
|
+
}
|
|
68
|
+
const mouseup = (e: MouseEvent) => {
|
|
69
|
+
if (DraggableController.enabled === false) return
|
|
70
|
+
DraggableController.end({ key: '', value: dataService.sidebar.url }, draggable, 'insert')
|
|
71
|
+
}
|
|
72
|
+
</script>
|
|
73
|
+
|
|
74
|
+
<style scoped lang="scss">
|
|
75
|
+
@import "devui-theme/styles-var/devui-var.scss";
|
|
76
|
+
|
|
77
|
+
.input-container {
|
|
78
|
+
width: 100%;
|
|
79
|
+
max-width: 1200px;
|
|
80
|
+
padding: 0 12px 12px 12px;
|
|
81
|
+
box-sizing: border-box;
|
|
82
|
+
|
|
83
|
+
.input-foot-wrapper {
|
|
84
|
+
display: flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
width: 100%;
|
|
87
|
+
height: 100%;
|
|
88
|
+
margin-right: 8px;
|
|
89
|
+
|
|
90
|
+
.input-word-container {
|
|
91
|
+
display: flex;
|
|
92
|
+
align-items: center;
|
|
93
|
+
gap: 4px;
|
|
94
|
+
height: 30px;
|
|
95
|
+
color: $devui-text;
|
|
96
|
+
font-size: $devui-font-size;
|
|
97
|
+
border-radius: 4px;
|
|
98
|
+
padding: 6px;
|
|
99
|
+
cursor: pointer;
|
|
100
|
+
|
|
101
|
+
svg {
|
|
102
|
+
width: 14px;
|
|
103
|
+
height: 14px;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
span {
|
|
107
|
+
font-size: $devui-font-size-sm;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
&:hover {
|
|
111
|
+
background-color: var(--devui-icon-hover-bg);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
span {
|
|
116
|
+
color: $devui-text;
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.input-foot-dividing-line {
|
|
121
|
+
width: 1px;
|
|
122
|
+
height: 14px;
|
|
123
|
+
background-color: $devui-line;
|
|
124
|
+
margin: 0 8px;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.input-foot-maxlength {
|
|
128
|
+
font-size: $devui-font-size-sm;
|
|
129
|
+
color: $devui-aide-text;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
:deep() {
|
|
134
|
+
.mc-button svg path {
|
|
135
|
+
transition: fill $devui-animation-duration-slow $devui-animation-ease-in-out-smooth;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.statement-box {
|
|
140
|
+
font-size: 12px;
|
|
141
|
+
margin-top: 8px;
|
|
142
|
+
color: $devui-aide-text;
|
|
143
|
+
text-align: center;
|
|
144
|
+
|
|
145
|
+
.separator {
|
|
146
|
+
height: 12px;
|
|
147
|
+
margin: 0 4px;
|
|
148
|
+
border: 0.6px solid $devui-disabled-text;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.link-span {
|
|
152
|
+
cursor: pointer;
|
|
153
|
+
text-decoration: underline;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.input-container {
|
|
159
|
+
:deep() {
|
|
160
|
+
.mc-button:disabled {
|
|
161
|
+
color: $devui-disabled-text;
|
|
162
|
+
background-color: $devui-disabled-bg;
|
|
163
|
+
|
|
164
|
+
svg path {
|
|
165
|
+
fill: $devui-disabled-text;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
</style>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="welcome-page">
|
|
3
|
+
<div class="content-wrapper">
|
|
4
|
+
<McIntroduction :logo-img="'logo/透明图标.png'" :title="'VYR'" :sub-title="''" :description="[
|
|
5
|
+
language.get('chat.introduction.title'),
|
|
6
|
+
language.get('chat.introduction.message'),
|
|
7
|
+
]" class="welcome-introduction">
|
|
8
|
+
</McIntroduction>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
import { McIntroduction } from '@matechat/core';
|
|
15
|
+
import { language } from '../locale';
|
|
16
|
+
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<style scoped lang="scss">
|
|
20
|
+
@import "devui-theme/styles-var/devui-var.scss";
|
|
21
|
+
|
|
22
|
+
.welcome-page {
|
|
23
|
+
flex: 1;
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
justify-content: flex-start;
|
|
27
|
+
box-sizing: border-box;
|
|
28
|
+
|
|
29
|
+
.content-wrapper {
|
|
30
|
+
margin: auto 0;
|
|
31
|
+
width: 100%;
|
|
32
|
+
gap: 24px;
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
min-height: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
overflow: auto;
|
|
39
|
+
width: 100%;
|
|
40
|
+
max-width: 1200px;
|
|
41
|
+
padding: 0 12px;
|
|
42
|
+
gap: 24px;
|
|
43
|
+
|
|
44
|
+
.welcome-introduction {
|
|
45
|
+
:deep() {
|
|
46
|
+
.mc-introduction-description {
|
|
47
|
+
font-size: var(--devui-font-size, 14px);
|
|
48
|
+
|
|
49
|
+
div {
|
|
50
|
+
line-height: 2;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
</style>
|