| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- <script lang="ts" setup>
- import { computed, nextTick, ref, watch } from 'vue'
- import InputTab from '@/features/RunWorkflow/components/InputTab.vue'
- import Chat from './Chat.vue'
- import ResizableDrawer from '@/components/ResizableDrawer/index.vue'
- import { useI18n } from '@/composables/useI18n'
- import { Icon, IconButton } from '@repo/ui'
- import type { IWorkflow, IWorkflowNode } from '@repo/workflow'
- import type { StartVariable } from '@/nodes/src/start'
- const props = withDefaults(
- defineProps<{
- visible: boolean
- workflow: IWorkflow
- startNode: IWorkflowNode | null
- visibleVariables: StartVariable[]
- inputValues: Record<string, any>
- jsonDrafts: Record<string, string>
- validationErrors: Record<string, string>
- baseParams: Record<string, any>
- isRunning: boolean
- }>(),
- {
- visible: false,
- startNode: null,
- baseParams: () => ({})
- }
- )
- const emit = defineEmits<{
- 'update:visible': [value: boolean]
- 'validate-send': [done: (params: Record<string, any> | false) => void]
- 'run-started': [nodeId: string]
- cancel: []
- }>()
- const { t } = useI18n()
- const showForm = ref(false)
- const chatContainerRef = ref<InstanceType<typeof Chat>>()
- const hasVisibleForm = computed(() => props.visibleVariables.length > 0)
- const closeDrawer = () => {
- handleDrawerUpdate(false)
- }
- const handleValidateSend = () =>
- new Promise<Record<string, any> | false>((resolve) => {
- emit('validate-send', resolve)
- })
- const handleDrawerUpdate = (value: boolean) => {
- if (!value) {
- handleCancel()
- }
- emit('update:visible', value)
- }
- const handleFirstSend = () => {
- if (hasVisibleForm.value) {
- showForm.value = false
- }
- }
- const handleResetConversation = () => {
- chatContainerRef.value?.resetConversation?.()
- if (hasVisibleForm.value) {
- showForm.value = true
- }
- }
- const handleCancel = () => {
- emit('cancel')
- }
- watch(
- () => [props.visible, hasVisibleForm.value],
- ([visible, hasForm]) => {
- if (!visible) return
- showForm.value = !!hasForm
- },
- { immediate: true }
- )
- defineExpose({
- scrollToBottom: () => {
- nextTick(() => {
- chatContainerRef.value?.scrollToBottom?.()
- })
- }
- })
- </script>
- <template>
- <div class="chat-drawer">
- <ResizableDrawer
- :visible="visible"
- :default-width="520"
- :min-width="420"
- :max-width-ratio="0.82"
- :z-index="1002"
- class="chat-drawer__panel"
- >
- <header class="chat-drawer__header">
- <h4>{{ t('pages.runWorkflow.chatDialogTitle') }}</h4>
- <span class="flex items-center gap-16px">
- <!-- 重置按钮 -->
- <Icon
- icon="lucide:refresh-ccw"
- height="18"
- width="18"
- class="cursor-pointer"
- @click="handleResetConversation"
- />
- <!-- 展示/隐藏表单 -->
- <IconButton
- v-if="hasVisibleForm"
- icon="lucide:sliders-horizontal"
- :type="showForm ? 'primary' : 'default'"
- :icon-color="showForm ? '#fff' : undefined"
- height="18"
- width="18"
- @click="showForm = !showForm"
- size="small"
- square
- />
- <!-- 关闭 -->
- <Icon
- icon="lucide:x"
- height="18"
- width="18"
- class="cursor-pointer"
- @click="closeDrawer"
- />
- </span>
- </header>
- <div class="chat-drawer__body">
- <div v-if="hasVisibleForm && showForm" class="chat-drawer__form">
- <el-card>
- <InputTab
- :start-node="startNode"
- :visible-variables="visibleVariables"
- :input-values="inputValues"
- :json-drafts="jsonDrafts"
- :validation-errors="validationErrors"
- :is-running="isRunning"
- :show-action-bar="false"
- :paneStyle="{ height: 'auto' }"
- />
- </el-card>
- </div>
- <div class="chat-drawer__chat">
- <Chat
- ref="chatContainerRef"
- :node="startNode || undefined"
- :workflow-id="workflow.id"
- :base-params="baseParams"
- :validate-before-send="handleValidateSend"
- :on-first-send="handleFirstSend"
- show-workflow-trace
- @run-started="emit('run-started', $event)"
- />
- </div>
- </div>
- </ResizableDrawer>
- </div>
- </template>
- <style lang="less" scoped>
- .chat-drawer {
- z-index: 1002;
- }
- .chat-drawer__header {
- height: 66px;
- padding: 16px 16px 0;
- display: flex;
- align-items: flex-start;
- justify-content: space-between;
- color: var(--text-primary);
- h4 {
- margin: 0;
- font-size: 15px;
- font-weight: 600;
- }
- }
- .chat-drawer__body {
- flex: 1;
- min-height: 0;
- display: flex;
- flex-direction: column;
- gap: 12px;
- overflow: hidden;
- border-radius: 8px;
- overflow-y: auto;
- }
- .chat-drawer__form {
- padding: 12px;
- flex-shrink: 0;
- max-height: 60%;
- overflow-y: auto;
- }
- .chat-drawer__chat {
- flex: 1;
- min-height: 0;
- }
- </style>
|