diff --git a/src/api/componentTestCase.ts b/src/api/componentTestCase.ts new file mode 100644 index 0000000..4464238 --- /dev/null +++ b/src/api/componentTestCase.ts @@ -0,0 +1,11 @@ +import axios from 'axios'; +import { apiResData } from '@/api/interface/index'; + +// 公共路径 +const urlPrefix = '/api/v1/bpms-workbench'; + +// 树形组件列表 +export function getTreeComponents(params?: { name: string, identifier: string, runStatus: string }) { + return axios.get(`${urlPrefix}/componentTestCase/tree/instance`, { params }); +} + diff --git a/src/pages/componentDevelopment/componentTest/index.tsx b/src/pages/componentDevelopment/componentTest/index.tsx index ddc4553..f653ed9 100644 --- a/src/pages/componentDevelopment/componentTest/index.tsx +++ b/src/pages/componentDevelopment/componentTest/index.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import styles from './style/index.module.less'; import { Button, Input, Radio, Space, Tag, Divider } from '@arco-design/web-react'; import { IconSearch } from '@arco-design/web-react/icon'; @@ -8,17 +8,35 @@ import InstanceList from '@/pages/componentDevelopment/componentTest/instanceLis const Group = Radio.Group; const ComponentTest = () => { + const [selectedIdentifier, setSelectedIdentifier] = useState(''); + const [refreshKey, setRefreshKey] = useState(0); + const [count, setCount] = useState({ total: 0, passed: 0, failed: 0 }); + + // 标签配置 + const tagList = [ + { label: '总数', value: count.total, color: 'purple' }, + { label: '已测试', value: count.passed, color: 'arcoblue' }, + { label: '未测试', value: count.failed, color: 'orangered' } + ]; + + // 处理子节点选择 + const handleNodeSelect = (identifier: string) => { + setSelectedIdentifier(identifier); + // 每次选择都更新 refreshKey,确保即使选择同一个节点也会触发刷新 + setRefreshKey(prev => prev + 1); + }; + return (
- {['总数126', '已测试45', '未测试81'].map((item, index) => { + {tagList.map((item) => { return ( - + {({ checked }) => { return ( - - {item} + + {item.label}{item.value} ); }} @@ -43,10 +61,10 @@ const ComponentTest = () => {
- + setCount(value)} />
- +
diff --git a/src/pages/componentDevelopment/componentTest/instanceList.tsx b/src/pages/componentDevelopment/componentTest/instanceList.tsx index 54fe967..fdd4cff 100644 --- a/src/pages/componentDevelopment/componentTest/instanceList.tsx +++ b/src/pages/componentDevelopment/componentTest/instanceList.tsx @@ -1,41 +1,97 @@ -import React from 'react'; -import { Button, Popconfirm, Table } from '@arco-design/web-react'; -import { IconDelete } from '@arco-design/web-react/icon'; +import React, { useEffect, useState } from 'react'; +import { Button, Table, TableColumnProps } from '@arco-design/web-react'; +import { getTreeComponents } from '@/api/componentTestCase'; +import { runStatusConstant, runStatusDic, runTypeConstant, runTypeDic } from '@/const/isdp/componentDeploy'; +import dayjs from 'dayjs'; -const InstanceList = () => { - const data = []; +const InstanceList = ({ identifier, refreshKey }: { identifier: string; refreshKey: number }) => { + const [data, setData] = useState([]); + const [loading, setLoading] = useState(false); + + // 获取实例列表数据 + const fetchInstanceData = async (identifier: string) => { + if (!identifier) { + setData([]); + return; + } + + setLoading(true); + try { + const res: any = await getTreeComponents({ identifier } as any); + + if (res.code === 200) { + // 直接使用 children 数据 + const instanceData = res.data?.[0]?.children || []; + setData(instanceData); + } + } catch (error) { + console.error('获取实例列表失败:', error); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchInstanceData(identifier); + }, [identifier, refreshKey]); // 定义表格列 - const columns = [ + const columns: TableColumnProps[] = [ { - title: '实例名', - dataIndex: 'name' + title: '实例标识', + dataIndex: 'identifier' }, { - title: '实例标识', - dataIndex: 'dataType' + title: '实例名', + dataIndex: 'name' }, { title: '运行类型', - dataIndex: 'defaultValue' + dataIndex: 'runType', + align: 'center', + render: (runType) => { + const item = runTypeDic.find(d => d.value === runTypeConstant[runType]); + return item ? item.label : '-'; + } }, { title: '实例状态', - dataIndex: 'description' + dataIndex: 'runStatus', + align: 'center', + render: (runStatus) => { + const item = runStatusDic.find(d => d.value === runStatus.toLowerCase()); + return item ? item.label : '-'; + } }, { title: '实例测试时间', - dataIndex: 'description1' + dataIndex: 'lastTestTime', + align: 'center', + render: (lastTestTime) => { + return lastTestTime ? dayjs(lastTestTime).format('YYYY-MM-DD HH:mm:ss') : '-'; + } }, { title: '操作', - dataIndex: 'operations' + dataIndex: 'operations', + align: 'center', + render: (col, record, index) => { + return ( + record.runStatus === 'RUN' && ( + + ) + ); + } } ]; + return ( diff --git a/src/pages/componentDevelopment/componentTest/sideBar.tsx b/src/pages/componentDevelopment/componentTest/sideBar.tsx index 0621fa0..97377fb 100644 --- a/src/pages/componentDevelopment/componentTest/sideBar.tsx +++ b/src/pages/componentDevelopment/componentTest/sideBar.tsx @@ -1,17 +1,121 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { Input, Tree } from '@arco-design/web-react'; import { IconSearch } from '@arco-design/web-react/icon'; import { menu } from './test/data'; +import { getTreeComponents } from '@/api/componentTestCase'; const TreeNode = Tree.Node; -const SideBar = () => { +const SideBar = ({ onNodeSelect, getCount }) => { const [searchValue, setSearchValue] = useState(''); + const [treeData, setTreeData] = useState([]); + const [originalData, setOriginalData] = useState([]); + const [expandedKeys, setExpandedKeys] = useState([]); const handleSearchChange = (value: string) => { setSearchValue(value); + + if (!value.trim()) { + // 搜索为空时,恢复原始数据并收起所有节点 + setTreeData(originalData); + setExpandedKeys([]); + return; + } + + // 过滤树形数据 + const filterTreeData = (data: any[]) => { + const filtered: any[] = []; + const expandKeys: string[] = []; + + data.forEach((classifyNode) => { + const filteredChildren = classifyNode.children.filter((child: any) => + child.title.toLowerCase().includes(value.toLowerCase()) + ); + + // 如果有匹配的子节点,或者分类名称匹配 + if ( + filteredChildren.length > 0 || + classifyNode.title.toLowerCase().includes(value.toLowerCase()) + ) { + filtered.push({ + ...classifyNode, + children: filteredChildren.length > 0 ? filteredChildren : classifyNode.children + }); + // 展开匹配的分类 + expandKeys.push(classifyNode.key); + } + }); + + return { filtered, expandKeys }; + }; + + const { filtered, expandKeys } = filterTreeData(originalData); + setTreeData(filtered); + setExpandedKeys(expandKeys); }; + // 根据 componentClassify 分类数据 + const formatTreeData = (data: any[]) => { + const classifyMap = new Map(); + + data.forEach((item) => { + const classify = item.componentClassify || '未分类'; + + if (!classifyMap.has(classify)) { + classifyMap.set(classify, { + title: classify, + key: `classify-${classify}`, + children: [] + }); + } + + + classifyMap.get(classify).children.push({ + title: item.name, + key: item.identifier, + data: item + }); + }); + + return Array.from(classifyMap.values()); + }; + + // 获取树形组件列表 + const fetchData = async () => { + const res: any = await getTreeComponents(); + + if (res.code === 200) { + const formattedData = formatTreeData(res.data); + setTreeData(formattedData); + setOriginalData(formattedData); + + const count = res.data.reduce((acc, item) => { + if (item.testCount > 0) { + acc.passed++; + } + else { + acc.failed++; + } + return acc; + }, { total: res.data.length, passed: 0, failed: 0 }); + getCount(count); + } + }; + + // 处理节点选择 + const handleTreeSelect = (selectedKeys: any[], info: any) => { + // 判断是否为子节点(不是分类节点) + const selectedKey = selectedKeys[0]; + if (selectedKey && !selectedKey.startsWith('classify-')) { + // 子节点的key就是identifier + onNodeSelect(selectedKey); + } + }; + + useEffect(() => { + fetchData(); + }, []); + return ( <> { /> { - console.log(value, info); - }} - onExpand={(keys, info) => { - console.log(keys, info); + onSelect={handleTreeSelect} + onExpand={(keys) => { + setExpandedKeys(keys as string[]); }} - treeData={menu} + expandedKeys={expandedKeys} + treeData={treeData} >