feat: execution detail
This commit is contained in:
parent
519e0dc60b
commit
005a6229fb
@ -1,56 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="execution-details-dialog responsive-dialog"
|
||||
:title="$t('chat.executionDetails.title')"
|
||||
v-model="dialogVisible"
|
||||
destroy-on-close
|
||||
append-to-body
|
||||
align-center
|
||||
@click.stop
|
||||
>
|
||||
<ExecutionDetailContent :detail="detail" :type="type" />
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onBeforeUnmount } from 'vue'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import ExecutionDetailContent from './component/ExecutionDetailContent.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
type?: string
|
||||
}>()
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const detail = ref<any[]>([])
|
||||
|
||||
watch(dialogVisible, (bool) => {
|
||||
if (!bool) {
|
||||
detail.value = []
|
||||
}
|
||||
})
|
||||
|
||||
const open = (data: any) => {
|
||||
detail.value = cloneDeep(data)
|
||||
dialogVisible.value = true
|
||||
}
|
||||
onBeforeUnmount(() => {
|
||||
dialogVisible.value = false
|
||||
})
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.execution-details-dialog {
|
||||
|
||||
.el-dialog__header {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.execution-details {
|
||||
max-height: calc(100vh - 260px);
|
||||
|
||||
.arrow-icon {
|
||||
transition: 0.2s;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="paragraph-source responsive-dialog"
|
||||
:title="$t('chat.paragraphSource.title')"
|
||||
v-model="dialogVisible"
|
||||
destroy-on-close
|
||||
append-to-body
|
||||
align-center
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
>
|
||||
<div class="mb-8">
|
||||
<ParagraphSourceContent :detail="detail"/>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onBeforeUnmount } from 'vue'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { arraySort } from '@/utils/array'
|
||||
import ParagraphSourceContent from './component/ParagraphSourceContent.vue'
|
||||
const emit = defineEmits(['refresh'])
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const detail = ref<any>({})
|
||||
|
||||
watch(dialogVisible, (bool) => {
|
||||
if (!bool) {
|
||||
detail.value = {}
|
||||
}
|
||||
})
|
||||
|
||||
const open = (data: any, id?: string) => {
|
||||
detail.value = cloneDeep(data)
|
||||
detail.value.paragraph_list = id
|
||||
? detail.value.paragraph_list.filter((v: any) => v.knowledge_id === id)
|
||||
: detail.value.paragraph_list
|
||||
detail.value.paragraph_list = arraySort(detail.value.paragraph_list, 'similarity', true)
|
||||
dialogVisible.value = true
|
||||
}
|
||||
onBeforeUnmount(() => {
|
||||
dialogVisible.value = false
|
||||
})
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.paragraph-source {
|
||||
padding: 0;
|
||||
|
||||
.el-dialog__header {
|
||||
padding: 24px 24px 0 24px;
|
||||
}
|
||||
.el-dialog__body {
|
||||
padding: 8px !important;
|
||||
}
|
||||
.paragraph-source-height {
|
||||
max-height: calc(100vh - 260px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,30 +0,0 @@
|
||||
<template>
|
||||
<el-scrollbar>
|
||||
<div class="paragraph-source-height p-16 pb-0">
|
||||
<el-form label-position="top">
|
||||
<el-form-item :label="$t('chat.paragraphSource.question')">
|
||||
<el-input :value="props.detail?.problem_text" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('chat.paragraphSource.optimizationQuestion')">
|
||||
<el-input :value="props.detail?.padding_problem_text" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('chat.KnowledgeSource.referenceParagraph')">
|
||||
<div v-if="props.detail?.paragraph_list.length > 0" class="w-full">
|
||||
<template v-for="(item, index) in props.detail.paragraph_list" :key="index">
|
||||
<ParagraphCard :data="item" :content="item.content" :index="index" />
|
||||
</template>
|
||||
</div>
|
||||
<span v-else> - </span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ParagraphCard from '@/components/ai-chat/component/ParagraphCard.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
detail?: any
|
||||
}>()
|
||||
</script>
|
||||
@ -40,7 +40,7 @@
|
||||
{{ $t('chat.tip.answerLoading') }} <span class="dotting"></span>
|
||||
</p>
|
||||
<!-- 知识来源 -->
|
||||
<KnowledgeSource
|
||||
<KnowledgeSourceComponent
|
||||
:data="chatRecord"
|
||||
:type="application.type"
|
||||
:executionIsRightPanel="props.executionIsRightPanel"
|
||||
@ -72,7 +72,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import KnowledgeSource from '@/components/ai-chat/KnowledgeSource.vue'
|
||||
import KnowledgeSourceComponent from '@/components/ai-chat/component/knowledge-source-component/index.vue'
|
||||
import MdRenderer from '@/components/markdown/MdRenderer.vue'
|
||||
import OperationButton from '@/components/ai-chat/component/operation-button/index.vue'
|
||||
import { type chatType } from '@/api/type/application'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-scrollbar>
|
||||
<div class="execution-details">
|
||||
<div class="execution-details p-8">
|
||||
<template
|
||||
v-if="isWorkFlow(props.type)"
|
||||
v-for="(item, index) in arraySort(props.detail ?? [], 'index')"
|
||||
@ -692,14 +692,38 @@
|
||||
</el-card>
|
||||
</template>
|
||||
<template v-else v-for="(item, index) in arraySort(props.detail ?? [], 'index')">
|
||||
<div class="card-never border-r-6 mb-12">
|
||||
<h5 class="p-8-12">
|
||||
{{ '-' }}
|
||||
</h5>
|
||||
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div class="mb-8">
|
||||
<span class="color-secondary"> {{ $t('chat.paragraphSource.question') }}:</span>
|
||||
|
||||
{{ item.question || '-' }}
|
||||
</div>
|
||||
|
||||
<template v-if="item.message_list?.length > 0">
|
||||
<p
|
||||
class="mt-4 mb-4"
|
||||
v-for="(content, contentIndex) in item.message_list"
|
||||
:key="contentIndex"
|
||||
>
|
||||
<span class="color-secondary mr-4">{{ content.role }}:</span
|
||||
><span>{{ content.content }}</span>
|
||||
</p>
|
||||
</template>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import ParagraphCard from '@/components/ai-chat/component/ParagraphCard.vue'
|
||||
import ParagraphCard from '@/components/ai-chat/component/knowledge-source-component/ParagraphCard.vue'
|
||||
import { arraySort } from '@/utils/array'
|
||||
import { iconComponent } from '@/workflow/icons/utils'
|
||||
import { WorkflowType } from '@/enums/application'
|
||||
@ -716,6 +740,7 @@ const current = ref<number | string>('')
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.execution-details {
|
||||
max-height: calc(100vh - 260px);
|
||||
.arrow-icon {
|
||||
transition: 0.2s;
|
||||
}
|
||||
@ -1,15 +1,13 @@
|
||||
<template>
|
||||
<CardBox
|
||||
shadow="never"
|
||||
:title="data.title || '-'"
|
||||
:title="index + 1 + '.' + data.title || '-'"
|
||||
class="paragraph-source-card cursor mb-8 paragraph-source-card-height"
|
||||
:class="data.is_active ? '' : 'disabled'"
|
||||
:showIcon="false"
|
||||
>
|
||||
<template #icon>
|
||||
<el-avatar class="mr-12 avatar-light" :size="22"> {{ index + 1 + '' }}</el-avatar>
|
||||
</template>
|
||||
<template #tag>
|
||||
<div class="primary">
|
||||
<div class="color-primary">
|
||||
{{ score?.toFixed(3) || data.similarity?.toFixed(3) }}
|
||||
</div>
|
||||
</template>
|
||||
@ -19,7 +17,7 @@
|
||||
</el-scrollbar>
|
||||
|
||||
<template #footer>
|
||||
<div class="footer-content flex-between">
|
||||
<el-card shadow="never" style="--el-card-padding: 8px" class="w-full mb-12">
|
||||
<el-text class="flex align-center item">
|
||||
<img :src="getImgUrl(data?.document_name?.trim())" alt="" width="20" class="mr-4" />
|
||||
|
||||
@ -39,15 +37,14 @@
|
||||
</span>
|
||||
</template>
|
||||
</el-text>
|
||||
<div class="flex align-center item" style="line-height: 32px">
|
||||
<el-avatar class="mr-8 avatar-blue" shape="square" :size="18">
|
||||
<img src="@/assets/knowledge/icon_document.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
|
||||
<span class="ellipsis-1 break-all" :title="data?.knowledge_name">
|
||||
{{ data?.knowledge_name }}</span
|
||||
>
|
||||
</div>
|
||||
</el-card>
|
||||
<div class="flex align-center border-t" style="padding: 12px 0 8px">
|
||||
<el-avatar class="mr-8 avatar-blue" shape="square" :size="18">
|
||||
<img src="@/assets/knowledge/icon_document.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
<span class="ellipsis-1 break-all" :title="data?.knowledge_name">
|
||||
{{ data?.knowledge_name || '-' }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</CardBox>
|
||||
@ -86,30 +83,13 @@ const parsedMeta = computed(() => {
|
||||
const meta = computed(() => (isMetaObject.value ? props.data.meta : parsedMeta.value))
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.paragraph-source-card {
|
||||
.footer-content {
|
||||
.item {
|
||||
max-width: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.paragraph-source-card-height {
|
||||
height: 260px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
.paragraph-source-card-height {
|
||||
height: 285px;
|
||||
}
|
||||
.paragraph-source-card {
|
||||
.footer-content {
|
||||
display: block;
|
||||
|
||||
.item {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// @media only screen and (max-width: 768px) {
|
||||
// .paragraph-source-card-height {
|
||||
// height: 285px;
|
||||
// }
|
||||
// }
|
||||
</style>
|
||||
@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<el-scrollbar>
|
||||
<div class="paragraph-source-height p-8">
|
||||
<div v-if="props.detail?.paragraph_list.length > 0" class="w-full">
|
||||
<template v-for="(item, index) in props.detail.paragraph_list" :key="index">
|
||||
<ParagraphCard :data="item" :content="item.content" :index="index" />
|
||||
</template>
|
||||
</div>
|
||||
<span v-else> - </span>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ParagraphCard from '@/components/ai-chat/component/knowledge-source-component/ParagraphCard.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
detail?: any
|
||||
}>()
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.paragraph-source-height {
|
||||
max-height: calc(100vh - 260px);
|
||||
}
|
||||
</style>
|
||||
@ -13,10 +13,10 @@
|
||||
<el-row :gutter="8" v-if="uniqueParagraphList?.length">
|
||||
<template v-for="(item, index) in uniqueParagraphList" :key="index">
|
||||
<el-col :span="12" class="mb-8">
|
||||
<el-card shadow="never" class="file-List-card" data-width="40">
|
||||
<el-card shadow="never" style="--el-card-padding: 8px">
|
||||
<div class="flex-between">
|
||||
<div class="flex">
|
||||
<img :src="getImgUrl(item && item?.document_name)" alt="" width="20" />
|
||||
<div class="flex align-center">
|
||||
<img :src="getImgUrl(item && item?.document_name)" alt="" width="24" />
|
||||
<div class="ml-4 ellipsis-1" :title="item?.document_name" v-if="!item.source_url">
|
||||
<p>{{ item && item?.document_name }}</p>
|
||||
</div>
|
||||
@ -24,7 +24,7 @@
|
||||
<a
|
||||
:href="getNormalizedUrl(item?.source_url)"
|
||||
target="_blank"
|
||||
class="ellipsis"
|
||||
class="ellipsis-1"
|
||||
:title="item?.document_name?.trim()"
|
||||
>
|
||||
<span :title="item?.document_name?.trim()">{{ item?.document_name }}</span>
|
||||
@ -60,18 +60,31 @@
|
||||
{{ $t('chat.executionDetails.title') }}</el-button
|
||||
>
|
||||
</div>
|
||||
<!-- 知识库引用 dialog -->
|
||||
<ParagraphSourceDialog ref="ParagraphSourceDialogRef" />
|
||||
<!-- 执行详情 dialog -->
|
||||
<ExecutionDetailDialog ref="ExecutionDetailDialogRef" :type="type" />
|
||||
<!-- 知识库引用/执行详情 dialog -->
|
||||
<el-dialog
|
||||
class="chat-source-dialog"
|
||||
:title="dialogTitle"
|
||||
v-model="dialogVisible"
|
||||
destroy-on-close
|
||||
append-to-body
|
||||
align-center
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
>
|
||||
<div class="mb-8">
|
||||
<component :is="currentComponent" :detail="currentChatDetail" :type="type"></component>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import ParagraphSourceDialog from './ParagraphSourceDialog.vue'
|
||||
import ExecutionDetailDialog from './ExecutionDetailDialog.vue'
|
||||
import { isWorkFlow } from '@/utils/application'
|
||||
import { computed, ref, shallowRef } from 'vue'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import ExecutionDetailContent from './ExecutionDetailContent.vue'
|
||||
import ParagraphSourceContent from './ParagraphSourceContent.vue'
|
||||
import { arraySort } from '@/utils/array'
|
||||
import { getImgUrl, getNormalizedUrl } from '@/utils/common'
|
||||
import { t } from '@/locales'
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
@ -89,21 +102,34 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['openExecutionDetail', 'openParagraph'])
|
||||
|
||||
const ParagraphSourceDialogRef = ref()
|
||||
const ExecutionDetailDialogRef = ref()
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('')
|
||||
const currentComponent = shallowRef<any>(null)
|
||||
const currentChatDetail = ref<any>(null)
|
||||
function openParagraph(row: any, id?: string) {
|
||||
dialogTitle.value = t('chat.KnowledgeSource.title')
|
||||
const obj = cloneDeep(row)
|
||||
obj.paragraph_list = id
|
||||
? obj.paragraph_list.filter((v: any) => v.knowledge_id === id)
|
||||
: obj.paragraph_list
|
||||
obj.paragraph_list = arraySort(obj.paragraph_list, 'similarity', true)
|
||||
if (props.executionIsRightPanel) {
|
||||
emit('openParagraph')
|
||||
return
|
||||
}
|
||||
ParagraphSourceDialogRef.value.open(row, id)
|
||||
currentComponent.value = ParagraphSourceContent
|
||||
currentChatDetail.value = obj
|
||||
dialogVisible.value = true
|
||||
}
|
||||
function openExecutionDetail(row: any) {
|
||||
dialogTitle.value = t('chat.executionDetails.title')
|
||||
if (props.executionIsRightPanel) {
|
||||
emit('openExecutionDetail')
|
||||
return
|
||||
}
|
||||
ExecutionDetailDialogRef.value.open(row)
|
||||
currentComponent.value = ExecutionDetailContent
|
||||
currentChatDetail.value = row
|
||||
dialogVisible.value = true
|
||||
}
|
||||
const uniqueParagraphList = computed(() => {
|
||||
const seen = new Set()
|
||||
@ -34,7 +34,7 @@
|
||||
</div>
|
||||
|
||||
<div class="card-footer flex-between" v-if="$slots.footer || $slots.mouseEnter">
|
||||
<div>
|
||||
<div style="flex: 1">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
<div @mouseenter="subHoveredEnter">
|
||||
|
||||
@ -214,3 +214,11 @@
|
||||
.auto-tooltip-popper {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
// 带滚动条dialog
|
||||
.chat-source-dialog {
|
||||
padding: 16px !important;
|
||||
.el-dialog__header {
|
||||
padding: 4px 16px 12px 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,8 +328,8 @@ import { useRouter } from 'vue-router'
|
||||
import ResetPassword from '@/layout/layout-header/avatar/ResetPassword.vue'
|
||||
import { t } from '@/locales'
|
||||
import type { ResetCurrentUserPasswordRequest } from '@/api/type/user'
|
||||
import ExecutionDetailContent from '@/components/ai-chat/component/ExecutionDetailContent.vue'
|
||||
import ParagraphSourceContent from '@/components/ai-chat/component/ParagraphSourceContent.vue'
|
||||
import ExecutionDetailContent from '@/components/ai-chat/component/knowledge-source-component/ExecutionDetailContent.vue'
|
||||
import ParagraphSourceContent from '@/components/ai-chat/component/knowledge-source-component/ParagraphSourceContent.vue'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
useResize()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user