Skip to content

Commit f06b67a

Browse files
perf: User input interaction style optimization
1 parent b8960d5 commit f06b67a

File tree

8 files changed

+155
-63
lines changed

8 files changed

+155
-63
lines changed

ui/src/components/ai-chat/component/chat-input-operate/index.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<template>
22
<div class="ai-chat__operate p-16-24">
33
<slot name="operateBefore" />
4-
54
<div class="operate-textarea">
65
<el-scrollbar max-height="136">
76
<div

ui/src/components/ai-chat/component/user-form/index.vue

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,16 @@
44
(inputFieldList.length > 0 || (type === 'debug-ai-chat' && apiInputFieldList.length > 0)) &&
55
type !== 'log'
66
"
7-
class="mb-16"
8-
style="padding: 0 24px"
7+
class="mb-16 w-full"
8+
style="padding: 0 24px; max-width: 400px"
99
>
1010
<el-card shadow="always" class="border-r-8" style="--el-card-padding: 16px 8px">
11-
<div
12-
class="flex align-center cursor w-full"
13-
style="padding: 0 8px"
14-
@click="showUserInput = !showUserInput"
15-
>
16-
<el-icon class="mr-8 arrow-icon" :class="showUserInput ? 'rotate-90' : ''"
11+
<div class="flex align-center cursor w-full" style="padding: 0 8px">
12+
<!-- <el-icon class="mr-8 arrow-icon" :class="showUserInput ? 'rotate-90' : ''"
1713
><CaretRight
18-
/></el-icon>
14+
/></el-icon> -->
1915
<span class="break-all ellipsis-1 mr-16" :title="inputFieldConfig.title">
20-
{{ inputFieldConfig.title }}
16+
{{ inputFieldConfig.title }}
2117
</span>
2218
</div>
2319
<el-scrollbar max-height="160">
@@ -44,6 +40,15 @@
4440
</div>
4541
</el-collapse-transition>
4642
</el-scrollbar>
43+
<div class="text-right mr-8">
44+
<el-button type="primary" v-if="first" @click="confirmHandle">{{
45+
$t('chat.operation.startChat')
46+
}}</el-button>
47+
<el-button v-if="!first" @click="cancelHandle">{{ $t('common.cancel') }}</el-button>
48+
<el-button type="primary" v-if="!first" @click="confirmHandle">{{
49+
$t('common.confirm')
50+
}}</el-button>
51+
</div>
4752
</el-card>
4853
</div>
4954
</template>
@@ -60,14 +65,15 @@ const props = defineProps<{
6065
type: 'log' | 'ai-chat' | 'debug-ai-chat'
6166
api_form_data: any
6267
form_data: any
68+
first: boolean
6369
}>()
6470
// 用于刷新动态表单
6571
const dynamicsFormRefresh = ref(0)
6672
const inputFieldList = ref<FormField[]>([])
6773
const apiInputFieldList = ref<FormField[]>([])
6874
const inputFieldConfig = ref({ title: t('chat.userInput') })
6975
const showUserInput = ref(true)
70-
const emit = defineEmits(['update:api_form_data', 'update:form_data'])
76+
const emit = defineEmits(['update:api_form_data', 'update:form_data', 'confirm', 'cancel'])
7177
7278
const api_form_data_context = computed({
7379
get: () => {
@@ -324,6 +330,14 @@ const decodeQuery = (query: string) => {
324330
return query
325331
}
326332
}
333+
const confirmHandle = () => {
334+
if (checkInputParam()) {
335+
emit('confirm')
336+
}
337+
}
338+
const cancelHandle = () => {
339+
emit('cancel')
340+
}
327341
defineExpose({ checkInputParam })
328342
onMounted(() => {
329343
handleInputFieldList()

ui/src/components/ai-chat/index.vue

Lines changed: 102 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,76 @@
11
<template>
22
<div ref="aiChatRef" class="ai-chat" :class="type">
3-
<UserForm
4-
v-model:api_form_data="api_form_data"
5-
v-model:form_data="form_data"
6-
:application="applicationDetails"
7-
:type="type"
8-
ref="userFormRef"
9-
></UserForm>
10-
<el-scrollbar ref="scrollDiv" @scroll="handleScrollTop">
11-
<div ref="dialogScrollbar" class="ai-chat__content p-24">
12-
<PrologueContent
13-
:type="type"
14-
:application="applicationDetails"
15-
:available="available"
16-
:send-message="sendMessage"
17-
></PrologueContent>
18-
19-
<template v-for="(item, index) in chatList" :key="index">
20-
<!-- 问题 -->
21-
<QuestionContent
3+
<div
4+
v-show="(isUserInput && firsUserInput) || showUserInput"
5+
:class="firsUserInput ? 'firstUserInput' : 'popperUserInput'"
6+
>
7+
<UserForm
8+
v-model:api_form_data="api_form_data"
9+
v-model:form_data="form_data"
10+
:application="applicationDetails"
11+
:type="type"
12+
:first="firsUserInput"
13+
@confirm="UserFormConfirm"
14+
@cancel="() => (showUserInput = false)"
15+
ref="userFormRef"
16+
></UserForm>
17+
</div>
18+
<template v-if="!firsUserInput">
19+
<el-scrollbar ref="scrollDiv" @scroll="handleScrollTop">
20+
<div ref="dialogScrollbar" class="ai-chat__content p-24">
21+
<PrologueContent
2222
:type="type"
2323
:application="applicationDetails"
24-
:chat-record="item"
25-
></QuestionContent>
26-
<!-- 回答 -->
27-
<AnswerContent
28-
:application="applicationDetails"
29-
:loading="loading"
30-
v-model:chat-record="chatList[index]"
31-
:type="type"
24+
:available="available"
3225
:send-message="sendMessage"
33-
:chat-management="ChatManagement"
34-
></AnswerContent>
26+
></PrologueContent>
27+
28+
<template v-for="(item, index) in chatList" :key="index">
29+
<!-- 问题 -->
30+
<QuestionContent
31+
:type="type"
32+
:application="applicationDetails"
33+
:chat-record="item"
34+
></QuestionContent>
35+
<!-- 回答 -->
36+
<AnswerContent
37+
:application="applicationDetails"
38+
:loading="loading"
39+
v-model:chat-record="chatList[index]"
40+
:type="type"
41+
:send-message="sendMessage"
42+
:chat-management="ChatManagement"
43+
></AnswerContent>
44+
</template>
45+
</div>
46+
</el-scrollbar>
47+
48+
<ChatInputOperate
49+
:app-id="appId"
50+
:application-details="applicationDetails"
51+
:is-mobile="isMobile"
52+
:type="type"
53+
:send-message="sendMessage"
54+
:open-chat-id="openChatId"
55+
:chat-management="ChatManagement"
56+
v-model:chat-id="chartOpenId"
57+
v-model:loading="loading"
58+
v-if="type !== 'log'"
59+
>
60+
<template #operateBefore>
61+
<div class="flex-between">
62+
<slot name="operateBefore">
63+
<span></span>
64+
</slot>
65+
<el-button class="user-input-button mb-8" type="primary" text @click="toggleUserInput">
66+
<AppIcon iconName="app-user-input"></AppIcon>
67+
</el-button>
68+
</div>
3569
</template>
36-
</div>
37-
</el-scrollbar>
70+
</ChatInputOperate>
3871

39-
<ChatInputOperate
40-
:app-id="appId"
41-
:application-details="applicationDetails"
42-
:is-mobile="isMobile"
43-
:type="type"
44-
:send-message="sendMessage"
45-
:open-chat-id="openChatId"
46-
:chat-management="ChatManagement"
47-
v-model:chat-id="chartOpenId"
48-
v-model:loading="loading"
49-
v-if="type !== 'log'"
50-
>
51-
<template #operateBefore> <slot name="operateBefore" /> </template>
52-
</ChatInputOperate>
53-
<Control></Control>
72+
<Control></Control>
73+
</template>
5474
</div>
5575
</template>
5676
<script setup lang="ts">
@@ -62,7 +82,7 @@ import { ChatManagement, type chatType } from '@/api/type/application'
6282
import { randomId } from '@/utils/utils'
6383
import useStore from '@/stores'
6484
import { isWorkFlow } from '@/utils/application'
65-
import { debounce } from 'lodash'
85+
import { debounce, first } from 'lodash'
6686
import AnswerContent from '@/components/ai-chat/component/answer-content/index.vue'
6787
import QuestionContent from '@/components/ai-chat/component/question-content/index.vue'
6888
import ChatInputOperate from '@/components/ai-chat/component/chat-input-operate/index.vue'
@@ -106,13 +126,25 @@ const chatList = ref<any[]>([])
106126
const form_data = ref<any>({})
107127
const api_form_data = ref<any>({})
108128
const userFormRef = ref<InstanceType<typeof UserForm>>()
129+
// 用户输入
130+
const firsUserInput = ref(true)
131+
const showUserInput = ref(false)
132+
133+
const isUserInput = computed(
134+
() =>
135+
props.applicationDetails.work_flow?.nodes?.filter((v: any) => v.id === 'base-node')[0]
136+
.properties.user_input_field_list.length > 0
137+
)
138+
109139
watch(
110140
() => props.chatId,
111141
(val) => {
112142
if (val && val !== 'new') {
113143
chartOpenId.value = val
144+
firsUserInput.value = false
114145
} else {
115146
chartOpenId.value = ''
147+
firsUserInput.value = true
116148
}
117149
},
118150
{ deep: true }
@@ -136,6 +168,15 @@ watch(
136168
}
137169
)
138170
171+
const toggleUserInput = () => {
172+
showUserInput.value = !showUserInput.value
173+
}
174+
175+
function UserFormConfirm() {
176+
firsUserInput.value = false
177+
showUserInput.value = false
178+
}
179+
139180
function sendMessage(val: string, other_params_data?: any, chat?: chatType) {
140181
if (!userFormRef.value?.checkInputParam()) {
141182
return
@@ -467,4 +508,18 @@ defineExpose({
467508
</script>
468509
<style lang="scss" scoped>
469510
@import './index.scss';
511+
.firstUserInput {
512+
height: 100%;
513+
display: flex;
514+
justify-content: center;
515+
align-items: center;
516+
}
517+
.popperUserInput {
518+
position: absolute;
519+
z-index: 999;
520+
right: 50px;
521+
bottom: 80px;
522+
width: calc(100% - 50px);
523+
max-width: 400px;
524+
}
470525
</style>

ui/src/components/icons/index.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,5 +1394,26 @@ export const iconMap: any = {
13941394
)
13951395
])
13961396
}
1397+
},
1398+
'app-user-input': {
1399+
iconReader: () => {
1400+
return h('i', [
1401+
h(
1402+
'svg',
1403+
{
1404+
style: { height: '100%', width: '100%' },
1405+
viewBox: '0 0 1024 1024',
1406+
version: '1.1',
1407+
xmlns: 'http://www.w3.org/2000/svg'
1408+
},
1409+
[
1410+
h('path', {
1411+
d: 'M85.333333 234.666667a149.333333 149.333333 0 0 1 292.48-42.666667H917.333333a21.333333 21.333333 0 0 1 21.333334 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333334 21.333333H377.813333A149.418667 149.418667 0 0 1 85.333333 234.666667z m21.333334 320a21.333333 21.333333 0 0 1-21.333334-21.333334v-42.666666a21.333333 21.333333 0 0 1 21.333334-21.333334h262.186666a149.418667 149.418667 0 0 1 286.293334 0H917.333333a21.333333 21.333333 0 0 1 21.333334 21.333334v42.666666a21.333333 21.333333 0 0 1-21.333334 21.333334h-262.186666a149.418667 149.418667 0 0 1-286.293334 0H106.666667z m405.333333 21.333333a64 64 0 1 0 0-128 64 64 0 0 0 0 128z m-405.333333 256A21.333333 21.333333 0 0 1 85.333333 810.666667v-42.666667a21.333333 21.333333 0 0 1 21.333334-21.333333h539.52a149.418667 149.418667 0 0 1 292.48 42.666666 149.333333 149.333333 0 0 1-292.48 42.666667H106.666667z m682.666666-106.666667a64 64 0 1 0 0 128 64 64 0 0 0 0-128zM234.666667 298.666667a64 64 0 1 0 0-128 64 64 0 0 0 0 128z',
1412+
fill: 'currentColor'
1413+
})
1414+
]
1415+
)
1416+
])
1417+
}
13971418
}
13981419
}

ui/src/locales/lang/en-US/ai-chat.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export default {
2323
oppose: 'Dislike',
2424
cancelOppose: 'Undo Dislike',
2525
continue: 'Continue',
26-
stopChat: 'Stop Response'
26+
stopChat: 'Stop Response',
27+
startChat: 'Start Response',
2728
},
2829
tip: {
2930
error500Message: 'Sorry, the service is currently under maintenance. Please try again later!',

ui/src/locales/lang/zh-CN/ai-chat.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export default {
2323
oppose: '反对',
2424
cancelOppose: '取消反对',
2525
continue: '继续',
26-
stopChat: '停止回答'
26+
stopChat: '停止回答',
27+
startChat: '开始回答',
2728
},
2829
tip: {
2930
error500Message: '抱歉,当前正在维护,无法提供服务,请稍后再试!',

ui/src/locales/lang/zh-Hant/ai-chat.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export default {
2323
oppose: '反對',
2424
cancelOppose: '取消反對',
2525
continue: '繼續',
26-
stopChat: '停止回答'
26+
stopChat: '停止回答',
27+
startChat: '開始回答',
2728
},
2829
tip: {
2930
error500Message: '抱歉,當前正在維護,無法提供服務,請稍後再試!',

ui/src/views/chat/pc/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@
156156
</el-button>
157157
</div>
158158
</div>
159+
<EditTitleDialog ref="EditTitleDialogRef" @refresh="refreshFieldTitle" />
159160
</div>
160-
<EditTitleDialog ref="EditTitleDialogRef" @refresh="refreshFieldTitle" />
161161
</template>
162162

163163
<script setup lang="ts">

0 commit comments

Comments
 (0)