feat(web): workflow app logs
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
import { type FC, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Flex, Button } from 'antd';
|
||||
import { Flex, Button, Form } from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
|
||||
import { getAppLogsUrl } from '@/api/application';
|
||||
@@ -15,11 +15,14 @@ import Table from '@/components/Table'
|
||||
import { formatDateTime } from '@/utils/format';
|
||||
import type { LogItem, LogDetailModalRef } from './types'
|
||||
import LogDetailModal from './components/LogDetailModal'
|
||||
import SearchInput from '@/components/SearchInput'
|
||||
|
||||
const Statistics: FC = () => {
|
||||
const { t } = useTranslation();
|
||||
const { id } = useParams();
|
||||
const logDetailRef = useRef<LogDetailModalRef>(null);
|
||||
const [form] = Form.useForm();
|
||||
const values = Form.useWatch([], form);
|
||||
|
||||
const handleViewDetail = (item: LogItem) => {
|
||||
logDetailRef.current?.handleOpen(item);
|
||||
@@ -62,15 +65,26 @@ const Statistics: FC = () => {
|
||||
];
|
||||
return (
|
||||
<div className="rb:bg-white rb:rounded-lg rb:pt-3 rb:px-3">
|
||||
<Flex justify="flex-end" className="rb:mb-3!">
|
||||
<Form form={form}>
|
||||
<Form.Item name="keyword" noStyle>
|
||||
<SearchInput
|
||||
placeholder={t('application.logSearchPlaceholder')}
|
||||
variant="outlined"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Flex>
|
||||
<Table<LogItem>
|
||||
apiUrl={getAppLogsUrl(id || '')}
|
||||
apiParams={{
|
||||
is_draft: false,
|
||||
...(values ?? {})
|
||||
}}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
isScroll={true}
|
||||
scrollY="calc(100vh - 214px)"
|
||||
scrollY="calc(100vh - 242px)"
|
||||
/>
|
||||
<LogDetailModal ref={logDetailRef} />
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-03-24 16:31:24
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 16:31:24
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-04-24 17:49:58
|
||||
*/
|
||||
import { forwardRef, useImperativeHandle, useState, useEffect } from 'react';
|
||||
import { Flex, Button, Empty, Skeleton } from 'antd';
|
||||
@@ -14,6 +14,12 @@ import { getAppLogDetail } from '@/api/application'
|
||||
import ChatContent from '@/components/Chat/ChatContent'
|
||||
import { formatDateTime } from '@/utils/format'
|
||||
import type { ChatItem } from '@/components/Chat/types'
|
||||
import Runtime from '@/views/Workflow/components/Chat/Runtime'
|
||||
import { nodeLibrary } from '@/views/Workflow/constant'
|
||||
|
||||
const nodeIconMap = Object.fromEntries(
|
||||
nodeLibrary.flatMap(c => c.nodes.map(n => [n.type, n.icon]))
|
||||
)
|
||||
|
||||
/** Log detail data with conversation messages */
|
||||
type Data = LogItem & {
|
||||
@@ -54,7 +60,30 @@ const LogDetailModal = forwardRef<LogDetailModalRef>((_props, ref) => {
|
||||
if (!vo) return
|
||||
setLoading(true)
|
||||
getAppLogDetail(vo.app_id, vo.id).then(res => {
|
||||
setData(res as Data)
|
||||
const { node_executions_map, messages, ...rest } = res as Data;
|
||||
let hasSubContentMessages = messages
|
||||
if (messages && messages.length > 0 && node_executions_map && Object.keys(node_executions_map).length > 0) {
|
||||
hasSubContentMessages = messages.map(item => {
|
||||
if (item.id && node_executions_map[item.id]) {
|
||||
item.subContent = node_executions_map[item.id]?.map(({ input, output, cycle_items = [], error, process, ...node }: any) => {
|
||||
const converted: any = { ...node, icon: nodeIconMap[node.node_type], content: { input, output, process, error } }
|
||||
if (node.node_type === 'loop' && Array.isArray(cycle_items) && cycle_items.length > 0) {
|
||||
converted.subContent = cycle_items.map(({ input: cInput, output: cOutput, error: cError, process: cProcess, ...cNode }: any) => ({
|
||||
...cNode,
|
||||
icon: nodeIconMap[cNode.node_type],
|
||||
content: { input: cInput, output: cOutput, process: cProcess, error: cError }
|
||||
}))
|
||||
}
|
||||
return converted
|
||||
})
|
||||
}
|
||||
return { ...item }
|
||||
})
|
||||
}
|
||||
setData({
|
||||
...rest,
|
||||
messages: hasSubContentMessages
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
@@ -66,6 +95,8 @@ const LogDetailModal = forwardRef<LogDetailModalRef>((_props, ref) => {
|
||||
handleClose
|
||||
}));
|
||||
|
||||
console.log('data', data)
|
||||
|
||||
return (
|
||||
<RbModal
|
||||
title={<>
|
||||
@@ -92,6 +123,7 @@ const LogDetailModal = forwardRef<LogDetailModalRef>((_props, ref) => {
|
||||
data={data.messages || []}
|
||||
streamLoading={false}
|
||||
labelFormat={(item) => formatDateTime(item.created_at)}
|
||||
renderRuntime={(item, index) => <Runtime item={item} index={index} />}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user