You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
9.6 KiB
TypeScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import React, { useEffect, useState } from 'react';
import {
Collapse,
Space,
Tag,
Button,
Table,
TableColumnProps,
Modal,
Dropdown,
Menu,
Pagination,
Message
} from '@arco-design/web-react';
import { IconDown, IconToBottom, IconEye } from '@arco-design/web-react/icon';
import styles from './style/collapseList.module.less';
import ListNode from '@/pages/componentDevelopment/componentDeployment/listNode';
import AddModal from '@/pages/componentDevelopment/componentDeployment/addModal';
import { componentOnSale, componentOffSale, getDeployList } from '@/api/componentDeploy';
import { runStatusConstant, runStatusDic } from '@/const/isdp/componentDeploy';
const CollapseItem = Collapse.Item;
interface CollapseListProps {
searchKeyword?: string;
runStatus?: string;
}
const CollapseList: React.FC<CollapseListProps> = ({ searchKeyword, runStatus }) => {
const [collapses, setCollapses] = useState([]);
const [visible, setVisible] = useState(false);
const [showOffSaleModal, setShowOffSaleModal] = useState(false);
const [selectedItem, setSelectedItem] = useState(null); // 选中的折叠面板数据
const [expandedItem, setExpandedItem] = useState(null); // 当前展开的折叠面板数据
const [addItem, setAddItem] = useState(null); // 点击新增实例按钮时记录当前信息
// 分页相关状态
const [current, setCurrent] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [total, setTotal] = useState(0);
// 获取组件列表
const getList = async (page = current, size = pageSize) => {
const params: any = {
current: page,
size: size
};
// 添加搜索关键词
if (searchKeyword) {
params.name = searchKeyword;
}
// 添加运行状态筛选
if (runStatus) {
params.runStatus = runStatus;
}
const res: any = await getDeployList(params);
if (res.code === 200) {
setCollapses(res.data.list.reverse());
setTotal(res.data.total || res.data.totalCount);
}
};
// 分页变化处理
const handlePageChange = (page: number, size: number) => {
setCurrent(page);
setPageSize(size);
getList(page, size);
};
// 上架组件
const componentOnSaleHandler = async (value) => {
const res: any = await componentOnSale({ identifier: value.identifier });
if (res.code === 200) {
Message.success({
content: '上架成功'
});
getList();
}
else {
Modal.error({
title: '上架失败',
content: res.message
});
}
};
// 下架组件
const componentOffSaleHandler = async (stopInstance: boolean) => {
const res: any = await componentOffSale({ identifier: selectedItem.identifier, stopInstance });
if (res.code === 200) {
Message.success({ content: '下架成功' });
getList();
setShowOffSaleModal(false);
}
else {
Modal.error({
title: '下架失败',
content: res.message
});
}
};
// 查看组件
const handleViewComponent = (item: any) => {
// 先触发跳转事件
const navigateEvent = new CustomEvent('navigateToTab', {
detail: {
path: 'componentList'
}
});
document.dispatchEvent(navigateEvent);
// 延迟触发搜索事件,确保页面已经切换
setTimeout(() => {
const searchEvent = new CustomEvent('componentListSearch', {
detail: {
searchKeyword: item.name
}
});
window.dispatchEvent(searchEvent);
}, 100);
};
useEffect(() => {
setCurrent(1); // 搜索条件变化时重置到第一页
getList(1, pageSize);
}, [searchKeyword, runStatus]);
// 折叠面板头部
const headerNode = (item) => {
const getRunStatus = () => {
return runStatusDic.find((v) => v.value === runStatusConstant[item.runStatus]) || {
color: 'gray',
label: '未知'
};
};
return (
<div className={styles['header-node']}>
<Space size={7} style={{ marginRight: 50 }}>
<img src="https://picsum.photos/200/300"
style={{ width: 50, height: 50, borderRadius: 6, overflow: 'hidden' }} />
<div>{item.name}</div>
</Space>
<Space size={10}>
<Tag>{item.componentClassify}</Tag>
<Tag>{item.codeLanguage}</Tag>
<Tag color={getRunStatus().color}>{getRunStatus().label}</Tag>
<div className={styles['flex-box']}>
<img src={'/icons/countIcon.png'} style={{ width: 16, height: 16, marginRight: 5 }} />
<span style={{ color: '#A2A2AB' }}> :</span>
<span style={{ color: '#A2A2AB' }}>{item.instanceCount}</span>
</div>
</Space>
</div>
);
};
// 折叠面板右侧的额外节点
const extraNode = (item) => {
return (
<div className={styles['extra-node']}>
<Space size={20}>
{/*新增实例*/}
{item.runStatus === 'RUN' && (
<div className={styles['flex-box']} onClick={() => {
setAddItem(item);
setVisible(true);
}}>
<img src={'/icons/addIcon.png'} style={{ width: 16, height: 16, marginRight: 5 }} />
<span style={{ color: '#A2A2AB' }}></span>
</div>
)}
{/*下架组件*/}
{item.runStatus === 'RUN' && (
<div className={`${styles['flex-box']} ${styles['custom-red']}`} onClick={() => {
setSelectedItem(item);
setShowOffSaleModal(true);
}}>
<img src={'/icons/removedIcon.png'} style={{ width: 16, height: 16, marginRight: 5 }} />
<span></span>
</div>
)}
{/*上架组件*/}
{item.runStatus === 'STOP' && (
<div className={`${styles['flex-box']} ${styles['custom-blue']}`}
onClick={() => componentOnSaleHandler(item)}>
<img src={'/icons/removedIcon.png'}
style={{ width: 16, height: 16, marginRight: 5, transform: 'rotate(180deg)' }} />
<span></span>
</div>
)}
{/*更多操作*/}
<Dropdown
droplist={
<Menu>
<Menu.Item key="viewComponent" onClick={() => handleViewComponent(item)}>
<span style={{ color: '#3491FA' }}>
<IconEye />
</span>
</Menu.Item>
</Menu>
}
position="br"
>
<div className={styles['flex-box']} style={{ cursor: 'pointer' }}>
<img src={'/icons/moreIcon.png'} style={{ width: 16, height: 16, marginRight: 5 }} />
<span style={{ color: '#A2A2AB' }}></span>
<IconDown style={{ fontSize: 12, marginLeft: 4, color: '#A2A2AB' }} />
</div>
</Dropdown>
</Space>
</div>
);
};
return (
<>
<div className={styles['collapse-list']}>
<Collapse
expandIconPosition={'right'}
bordered={false}
onChange={(key, keys, e) => {
// 当展开某个折叠面板时,记录当前展开的 item 数据
if (keys && keys.length > 0) {
// 获取最后一个展开的 key当前操作的 key
const expandedKey = keys[keys.length - 1];
const expandedIndex = parseInt(expandedKey, 10);
const currentItem = collapses[expandedIndex];
setExpandedItem(currentItem);
}
else {
// 所有面板都折叠时,清空 expandedItem
setExpandedItem(null);
}
}}
>
{collapses.map((item, index) => (
<CollapseItem
key={item.identifier}
header={headerNode(item)}
name={index.toString()}
extra={extraNode(item)}
>
<ListNode componentData={item} />
</CollapseItem>
))}
</Collapse>
{/* 分页组件 */}
{total > 0 && (
<div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: 16 }}>
<Pagination
current={current}
pageSize={pageSize}
total={total}
// showTotal
pageSizeChangeResetCurrent
onChange={(page) => handlePageChange(page, pageSize)}
/>
</div>
)}
</div>
<AddModal
addItem={addItem}
visible={visible}
setVisible={setVisible}
onSuccess={getList}
/>
<Modal
title={'下架组件'}
visible={showOffSaleModal}
style={{ width: '45%' }}
onCancel={() => {
setSelectedItem(null);
setShowOffSaleModal(false);
}}
footer={[
<Button key="cancel" onClick={() => setShowOffSaleModal(false)}>
</Button>,
<Button key="offshelf" type="primary" onClick={() => {
componentOffSaleHandler(false);
}}>
</Button>,
<Button key="stopAndOffshelf" type="primary" status="danger" onClick={() => {
componentOffSaleHandler(true);
}}>
线
</Button>
]}
>
<p></p>
<p> 线使线</p>
</Modal>
</>
);
};
export default CollapseList;