mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
perf: User input interaction style optimization
This commit is contained in:
parent
b8960d57c8
commit
a09f5c0577
|
|
@ -1,7 +1,6 @@
|
|||
<template>
|
||||
<div class="ai-chat__operate p-16-24">
|
||||
<slot name="operateBefore" />
|
||||
|
||||
<div class="operate-textarea">
|
||||
<el-scrollbar max-height="136">
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -4,20 +4,16 @@
|
|||
(inputFieldList.length > 0 || (type === 'debug-ai-chat' && apiInputFieldList.length > 0)) &&
|
||||
type !== 'log'
|
||||
"
|
||||
class="mb-16"
|
||||
style="padding: 0 24px"
|
||||
class="mb-16 w-full"
|
||||
style="padding: 0 24px; max-width: 400px"
|
||||
>
|
||||
<el-card shadow="always" class="border-r-8" style="--el-card-padding: 16px 8px">
|
||||
<div
|
||||
class="flex align-center cursor w-full"
|
||||
style="padding: 0 8px"
|
||||
@click="showUserInput = !showUserInput"
|
||||
>
|
||||
<el-icon class="mr-8 arrow-icon" :class="showUserInput ? 'rotate-90' : ''"
|
||||
<div class="flex align-center cursor w-full" style="padding: 0 8px">
|
||||
<!-- <el-icon class="mr-8 arrow-icon" :class="showUserInput ? 'rotate-90' : ''"
|
||||
><CaretRight
|
||||
/></el-icon>
|
||||
/></el-icon> -->
|
||||
<span class="break-all ellipsis-1 mr-16" :title="inputFieldConfig.title">
|
||||
{{ inputFieldConfig.title }}
|
||||
{{ inputFieldConfig.title }}
|
||||
</span>
|
||||
</div>
|
||||
<el-scrollbar max-height="160">
|
||||
|
|
@ -44,6 +40,15 @@
|
|||
</div>
|
||||
</el-collapse-transition>
|
||||
</el-scrollbar>
|
||||
<div class="text-right mr-8">
|
||||
<el-button type="primary" v-if="first" @click="confirmHandle">{{
|
||||
$t('chat.operation.startChat')
|
||||
}}</el-button>
|
||||
<el-button v-if="!first" @click="cancelHandle">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button type="primary" v-if="!first" @click="confirmHandle">{{
|
||||
$t('common.confirm')
|
||||
}}</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -60,6 +65,7 @@ const props = defineProps<{
|
|||
type: 'log' | 'ai-chat' | 'debug-ai-chat'
|
||||
api_form_data: any
|
||||
form_data: any
|
||||
first: boolean
|
||||
}>()
|
||||
// 用于刷新动态表单
|
||||
const dynamicsFormRefresh = ref(0)
|
||||
|
|
@ -67,7 +73,7 @@ const inputFieldList = ref<FormField[]>([])
|
|||
const apiInputFieldList = ref<FormField[]>([])
|
||||
const inputFieldConfig = ref({ title: t('chat.userInput') })
|
||||
const showUserInput = ref(true)
|
||||
const emit = defineEmits(['update:api_form_data', 'update:form_data'])
|
||||
const emit = defineEmits(['update:api_form_data', 'update:form_data', 'confirm', 'cancel'])
|
||||
|
||||
const api_form_data_context = computed({
|
||||
get: () => {
|
||||
|
|
@ -324,6 +330,14 @@ const decodeQuery = (query: string) => {
|
|||
return query
|
||||
}
|
||||
}
|
||||
const confirmHandle = () => {
|
||||
if (checkInputParam()) {
|
||||
emit('confirm')
|
||||
}
|
||||
}
|
||||
const cancelHandle = () => {
|
||||
emit('cancel')
|
||||
}
|
||||
defineExpose({ checkInputParam })
|
||||
onMounted(() => {
|
||||
handleInputFieldList()
|
||||
|
|
|
|||
|
|
@ -1,56 +1,76 @@
|
|||
<template>
|
||||
<div ref="aiChatRef" class="ai-chat" :class="type">
|
||||
<UserForm
|
||||
v-model:api_form_data="api_form_data"
|
||||
v-model:form_data="form_data"
|
||||
:application="applicationDetails"
|
||||
:type="type"
|
||||
ref="userFormRef"
|
||||
></UserForm>
|
||||
<el-scrollbar ref="scrollDiv" @scroll="handleScrollTop">
|
||||
<div ref="dialogScrollbar" class="ai-chat__content p-24">
|
||||
<PrologueContent
|
||||
:type="type"
|
||||
:application="applicationDetails"
|
||||
:available="available"
|
||||
:send-message="sendMessage"
|
||||
></PrologueContent>
|
||||
|
||||
<template v-for="(item, index) in chatList" :key="index">
|
||||
<!-- 问题 -->
|
||||
<QuestionContent
|
||||
:type="type"
|
||||
:application="applicationDetails"
|
||||
:chat-record="item"
|
||||
></QuestionContent>
|
||||
<!-- 回答 -->
|
||||
<AnswerContent
|
||||
:application="applicationDetails"
|
||||
:loading="loading"
|
||||
v-model:chat-record="chatList[index]"
|
||||
:type="type"
|
||||
:send-message="sendMessage"
|
||||
:chat-management="ChatManagement"
|
||||
></AnswerContent>
|
||||
</template>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
|
||||
<ChatInputOperate
|
||||
:app-id="appId"
|
||||
:application-details="applicationDetails"
|
||||
:is-mobile="isMobile"
|
||||
:type="type"
|
||||
:send-message="sendMessage"
|
||||
:open-chat-id="openChatId"
|
||||
:chat-management="ChatManagement"
|
||||
v-model:chat-id="chartOpenId"
|
||||
v-model:loading="loading"
|
||||
v-if="type !== 'log'"
|
||||
<div
|
||||
v-show="(isUserInput && firsUserInput) || showUserInput"
|
||||
:class="firsUserInput ? 'firstUserInput' : 'popperUserInput'"
|
||||
>
|
||||
<template #operateBefore> <slot name="operateBefore" /> </template>
|
||||
</ChatInputOperate>
|
||||
<Control></Control>
|
||||
<UserForm
|
||||
v-model:api_form_data="api_form_data"
|
||||
v-model:form_data="form_data"
|
||||
:application="applicationDetails"
|
||||
:type="type"
|
||||
:first="firsUserInput"
|
||||
@confirm="UserFormConfirm"
|
||||
@cancel="() => (showUserInput = false)"
|
||||
ref="userFormRef"
|
||||
></UserForm>
|
||||
</div>
|
||||
<template v-if="!firsUserInput">
|
||||
<el-scrollbar ref="scrollDiv" @scroll="handleScrollTop">
|
||||
<div ref="dialogScrollbar" class="ai-chat__content p-24">
|
||||
<PrologueContent
|
||||
:type="type"
|
||||
:application="applicationDetails"
|
||||
:available="available"
|
||||
:send-message="sendMessage"
|
||||
></PrologueContent>
|
||||
|
||||
<template v-for="(item, index) in chatList" :key="index">
|
||||
<!-- 问题 -->
|
||||
<QuestionContent
|
||||
:type="type"
|
||||
:application="applicationDetails"
|
||||
:chat-record="item"
|
||||
></QuestionContent>
|
||||
<!-- 回答 -->
|
||||
<AnswerContent
|
||||
:application="applicationDetails"
|
||||
:loading="loading"
|
||||
v-model:chat-record="chatList[index]"
|
||||
:type="type"
|
||||
:send-message="sendMessage"
|
||||
:chat-management="ChatManagement"
|
||||
></AnswerContent>
|
||||
</template>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
|
||||
<ChatInputOperate
|
||||
:app-id="appId"
|
||||
:application-details="applicationDetails"
|
||||
:is-mobile="isMobile"
|
||||
:type="type"
|
||||
:send-message="sendMessage"
|
||||
:open-chat-id="openChatId"
|
||||
:chat-management="ChatManagement"
|
||||
v-model:chat-id="chartOpenId"
|
||||
v-model:loading="loading"
|
||||
v-if="type !== 'log'"
|
||||
>
|
||||
<template #operateBefore>
|
||||
<div class="flex-between">
|
||||
<slot name="operateBefore">
|
||||
<span></span>
|
||||
</slot>
|
||||
<el-button class="user-input-button mb-8" type="primary" text @click="toggleUserInput">
|
||||
<AppIcon iconName="app-user-input"></AppIcon>
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</ChatInputOperate>
|
||||
|
||||
<Control></Control>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
|
@ -62,7 +82,7 @@ import { ChatManagement, type chatType } from '@/api/type/application'
|
|||
import { randomId } from '@/utils/utils'
|
||||
import useStore from '@/stores'
|
||||
import { isWorkFlow } from '@/utils/application'
|
||||
import { debounce } from 'lodash'
|
||||
import { debounce, first } from 'lodash'
|
||||
import AnswerContent from '@/components/ai-chat/component/answer-content/index.vue'
|
||||
import QuestionContent from '@/components/ai-chat/component/question-content/index.vue'
|
||||
import ChatInputOperate from '@/components/ai-chat/component/chat-input-operate/index.vue'
|
||||
|
|
@ -106,13 +126,25 @@ const chatList = ref<any[]>([])
|
|||
const form_data = ref<any>({})
|
||||
const api_form_data = ref<any>({})
|
||||
const userFormRef = ref<InstanceType<typeof UserForm>>()
|
||||
// 用户输入
|
||||
const firsUserInput = ref(true)
|
||||
const showUserInput = ref(false)
|
||||
|
||||
const isUserInput = computed(
|
||||
() =>
|
||||
props.applicationDetails.work_flow?.nodes?.filter((v: any) => v.id === 'base-node')[0]
|
||||
.properties.user_input_field_list.length > 0
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.chatId,
|
||||
(val) => {
|
||||
if (val && val !== 'new') {
|
||||
chartOpenId.value = val
|
||||
firsUserInput.value = false
|
||||
} else {
|
||||
chartOpenId.value = ''
|
||||
firsUserInput.value = true
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
|
|
@ -136,6 +168,15 @@ watch(
|
|||
}
|
||||
)
|
||||
|
||||
const toggleUserInput = () => {
|
||||
showUserInput.value = !showUserInput.value
|
||||
}
|
||||
|
||||
function UserFormConfirm() {
|
||||
firsUserInput.value = false
|
||||
showUserInput.value = false
|
||||
}
|
||||
|
||||
function sendMessage(val: string, other_params_data?: any, chat?: chatType) {
|
||||
if (!userFormRef.value?.checkInputParam()) {
|
||||
return
|
||||
|
|
@ -467,4 +508,18 @@ defineExpose({
|
|||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
.firstUserInput {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.popperUserInput {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
right: 50px;
|
||||
bottom: 80px;
|
||||
width: calc(100% - 50px);
|
||||
max-width: 400px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1394,5 +1394,26 @@ export const iconMap: any = {
|
|||
)
|
||||
])
|
||||
}
|
||||
},
|
||||
'app-user-input': {
|
||||
iconReader: () => {
|
||||
return h('i', [
|
||||
h(
|
||||
'svg',
|
||||
{
|
||||
style: { height: '100%', width: '100%' },
|
||||
viewBox: '0 0 1024 1024',
|
||||
version: '1.1',
|
||||
xmlns: 'http://www.w3.org/2000/svg'
|
||||
},
|
||||
[
|
||||
h('path', {
|
||||
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',
|
||||
fill: 'currentColor'
|
||||
})
|
||||
]
|
||||
)
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ export default {
|
|||
oppose: 'Dislike',
|
||||
cancelOppose: 'Undo Dislike',
|
||||
continue: 'Continue',
|
||||
stopChat: 'Stop Response'
|
||||
stopChat: 'Stop Response',
|
||||
startChat: 'Start Response',
|
||||
},
|
||||
tip: {
|
||||
error500Message: 'Sorry, the service is currently under maintenance. Please try again later!',
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ export default {
|
|||
oppose: '反对',
|
||||
cancelOppose: '取消反对',
|
||||
continue: '继续',
|
||||
stopChat: '停止回答'
|
||||
stopChat: '停止回答',
|
||||
startChat: '开始回答',
|
||||
},
|
||||
tip: {
|
||||
error500Message: '抱歉,当前正在维护,无法提供服务,请稍后再试!',
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ export default {
|
|||
oppose: '反對',
|
||||
cancelOppose: '取消反對',
|
||||
continue: '繼續',
|
||||
stopChat: '停止回答'
|
||||
stopChat: '停止回答',
|
||||
startChat: '開始回答',
|
||||
},
|
||||
tip: {
|
||||
error500Message: '抱歉,當前正在維護,無法提供服務,請稍後再試!',
|
||||
|
|
|
|||
|
|
@ -156,8 +156,8 @@
|
|||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<EditTitleDialog ref="EditTitleDialogRef" @refresh="refreshFieldTitle" />
|
||||
</div>
|
||||
<EditTitleDialog ref="EditTitleDialogRef" @refresh="refreshFieldTitle" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
|||
Loading…
Reference in New Issue